blob: e2064c9dbe887dbb38d511d27453592faabcb7ce [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003# ABI Compliance Checker (ACC) 1.99.4
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 Ponomarenkoe3a8d812013-06-28 12:50:10 +040067my $TOOL_VERSION = "1.99.4";
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
2556 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002557 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002558
2559 return "$NewId";
2560}
2561
2562sub instType($$$)
2563{ # create template instances
2564 my ($Map, $Tid, $LibVersion) = @_;
2565 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2566
2567 foreach my $Key (sort keys(%{$Map}))
2568 {
2569 if(my $Val = $Map->{$Key})
2570 {
2571 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2572
2573 if(defined $Attr->{"NameSpace"}) {
2574 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2575 }
2576 foreach (keys(%{$Attr->{"TParam"}})) {
2577 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2578 }
2579 }
2580 else
2581 { # remove absent
2582 # _Traits, etc.
2583 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002584 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002585 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2586 }
2587 foreach (keys(%{$Attr->{"TParam"}}))
2588 {
2589 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2590 delete($Attr->{"TParam"}{$_});
2591 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002592 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002593 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2594 }
2595 }
2596 }
2597 }
2598
2599 my $Tmpl = 0;
2600
2601 if(defined $Attr->{"TParam"})
2602 {
2603 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2604 {
2605 my $PName = $Attr->{"TParam"}{$_}{"name"};
2606
2607 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2608 {
2609 my %Base = get_BaseType($PTid, $LibVersion);
2610
2611 if($Base{"Type"} eq "TemplateParam"
2612 or defined $Base{"Template"})
2613 {
2614 $Tmpl = 1;
2615 last
2616 }
2617 }
2618 }
2619 }
2620
2621 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2622 return "$Id";
2623 }
2624 else
2625 {
2626 if(not $Tmpl) {
2627 delete($Attr->{"Template"});
2628 }
2629
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002630 my $New = createType($Attr, $LibVersion);
2631
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002632 my %EMap = ();
2633 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2634 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2635 }
2636 foreach (keys(%{$Map})) {
2637 $EMap{$_} = $Map->{$_};
2638 }
2639
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002640 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2641 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002642 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002643 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002644 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002645 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002646 {
2647 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2648
2649 if($NBid ne $Bid)
2650 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002651 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2652 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002653 }
2654 }
2655 }
2656
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002657 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002658 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002659 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}})) {
2660 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002661 }
2662 }
2663
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002664 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002665 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002666 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2667 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002668 }
2669 }
2670
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002671 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2672 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002673 }
2674
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002675 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002676 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002677}
2678
2679sub addMissedTypes_Pre()
2680{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002681 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002682 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2683 { # detecting missed typedefs
2684 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2685 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002686 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002687 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002688 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002689 if($TypeType eq "Unknown")
2690 { # template_type_parm
2691 next;
2692 }
2693 my $TypeDeclId = getTypeDeclId($TypeId);
2694 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2695 my $TypedefName = getNameByInfo($MissedTDid);
2696 next if(not $TypedefName);
2697 next if($TypedefName eq "__float80");
2698 next if(isAnon($TypedefName));
2699 if(not $TypeDeclId
2700 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002701 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002702 }
2703 }
2704 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002705 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002706 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002707 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002708 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002709 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002710 next;
2711 }
2712 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002713 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002714 if(not $TypedefName) {
2715 next;
2716 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002717 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002718 my %MissedInfo = ( # typedef info
2719 "Name" => $TypedefName,
2720 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002721 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002722 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002723 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002724 my ($H, $L) = getLocation($MissedTDid);
2725 $MissedInfo{"Header"} = $H;
2726 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002727 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002728 { # other types
2729 next;
2730 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002731 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002732 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002733 next;
2734 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002735 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002736 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002737 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002738 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002739 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002740 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002741 next;
2742 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002743 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002744 next;
2745 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002746 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002747 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002748 next;
2749 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002750 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002751 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002752 next;
2753 }
2754 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002755
2756 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2757
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002758 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002759 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002760 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002761 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002762 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002763
2764 # add missed & remove other
2765 $TypeInfo{$Version} = \%AddTypes;
2766 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002767}
2768
2769sub addMissedTypes_Post()
2770{
2771 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2772 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002773 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2774 {
2775 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2776 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2777 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2778 }
2779 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002780 }
2781}
2782
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002783sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002784{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002785 my $TypeId = $_[0];
2786 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2787 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002788 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002789 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002790 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002791}
2792
2793sub getArraySize($$)
2794{
2795 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002796 if(my $Size = getSize($TypeId))
2797 {
2798 my $Elems = $Size/$BYTE_SIZE;
2799 while($BaseName=~s/\s*\[(\d+)\]//) {
2800 $Elems/=$1;
2801 }
2802 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2803 {
2804 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2805 $Elems/=$BasicSize;
2806 }
2807 }
2808 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002809 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002810 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002811}
2812
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002813sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002814{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002815 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002816 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002817 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2818 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002819 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002820 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2821 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2822 if(not $NodeType)
2823 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002824 return ();
2825 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002826 if($NodeType eq "tree_vec")
2827 {
2828 if($Pos!=$#Positions)
2829 { # select last vector of parameters ( ns<P1>::type<P2> )
2830 next;
2831 }
2832 }
2833 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2834 foreach my $P (@Params)
2835 {
2836 if($P eq "") {
2837 return ();
2838 }
2839 elsif($P ne "\@skip\@") {
2840 @TmplParams = (@TmplParams, $P);
2841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002842 }
2843 }
2844 return @TmplParams;
2845}
2846
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002847sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002848{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002849 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002850 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002851 if(defined $TypeInfo{$Version}{$TypeId}
2852 and $TypeInfo{$Version}{$TypeId}{"Name"})
2853 { # already created
2854 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002855 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002856 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2857 { # incomplete type
2858 return ();
2859 }
2860 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2861
2862 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002863 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002864
2865 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2866 {
2867 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2868 {
2869 if($Info=~/qual[ ]*:/)
2870 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002871 my $NewId = ++$MAX_ID;
2872
2873 $MissedBase{$Version}{$TypeId} = "$NewId";
2874 $MissedBase_R{$Version}{$NewId} = $TypeId;
2875 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2876 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002877 }
2878 }
2879 $TypeAttr{"Type"} = "Typedef";
2880 }
2881 else {
2882 $TypeAttr{"Type"} = getTypeType($TypeId);
2883 }
2884
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002885 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2886 {
2887 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2888 { # local code
2889 return ();
2890 }
2891 }
2892
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002893 if($TypeAttr{"Type"} eq "Unknown") {
2894 return ();
2895 }
2896 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2897 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002898 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002899 if(my $TName = $TypeAttr{"Name"})
2900 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002901 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002902 $TName_Tid{$Version}{$TName} = $TypeId;
2903 return %TypeAttr;
2904 }
2905 else {
2906 return ();
2907 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002908 }
2909 elsif($TypeAttr{"Type"} eq "Array")
2910 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002911 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2912 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002913 return ();
2914 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002915 if(my $Algn = getAlgn($TypeId)) {
2916 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2917 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002918 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002919 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002920 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002921 if(not $BTAttr{"Name"}) {
2922 return ();
2923 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002924 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002925 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002926 if(my $Size = getSize($TypeId)) {
2927 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2928 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002929 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002930 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2931 }
2932 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002933 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002935 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002936 else
2937 {
2938 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002939 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002940 $TypeAttr{"Name"} = $1."[]".$2;
2941 }
2942 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002943 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002944 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002945 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002946 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002947 if($BTAttr{"Header"}) {
2948 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002949 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002950 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002951 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2952 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002953 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002954 return ();
2955 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002956 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002957 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002958 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002959 if($TypeAttr{"Name"})
2960 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002961 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002962
2963 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2964 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002965 { # NOTE: register only one int: with built-in decl
2966 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2967 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2968 }
2969 }
2970 return %TypeAttr;
2971 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002972 else {
2973 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002974 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002975 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002976 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2977 {
2978 %TypeAttr = getTrivialTypeAttr($TypeId);
2979 if($TypeAttr{"Name"})
2980 {
2981 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2982 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2983 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2984 }
2985 return %TypeAttr;
2986 }
2987 else {
2988 return ();
2989 }
2990 }
2991 elsif($TypeAttr{"Type"} eq "SizeOf")
2992 {
2993 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2994 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2995 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2996 if($TypeAttr{"Name"})
2997 {
2998 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2999 return %TypeAttr;
3000 }
3001 else {
3002 return ();
3003 }
3004 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003005 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003006 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003007 my ($BTid, $BTSpec) = selectBaseType($TypeId);
3008 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003009 return ();
3010 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003011 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003012 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003013 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003014 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003015 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003016 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003017 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003018 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003019 }
3020 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003021 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003022 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003023 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003024 return ();
3025 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003026 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003027 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003028 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003029 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003030 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003031 }
3032 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003033 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003034 {
3035 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003036 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003037 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003038 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003039 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
3040 }
3041 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003042 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003043 }
3044 }
3045 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003046 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003047 }
3048 if($TypeAttr{"Type"} eq "Typedef")
3049 {
3050 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003051
3052 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
3053 return ();
3054 }
3055
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003056 if(isAnon($TypeAttr{"Name"}))
3057 { # anon typedef to anon type: ._N
3058 return ();
3059 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003060
3061 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
3062 { # artificial typedef of "struct X" to "X"
3063 $TypeAttr{"Artificial"} = 1;
3064 }
3065
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003066 if(my $NS = getNameSpace($TypeDeclId))
3067 {
3068 my $TypeName = $TypeAttr{"Name"};
3069 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
3070 { # "some_type" is the typedef to "struct some_type" in C++
3071 if($3) {
3072 $TypeAttr{"Name"} = $3."::".$TypeName;
3073 }
3074 }
3075 else
3076 {
3077 $TypeAttr{"NameSpace"} = $NS;
3078 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003079
3080 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
3081 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
3082 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003083 if($BTAttr{"NameSpace"}
3084 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003085 { # types like "std::fpos<__mbstate_t>" are
3086 # not covered by typedefs in the TU dump
3087 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003088 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3089 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003090 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003091 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003092 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003093 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003094 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003095 }
3096 }
3097 }
3098 }
3099 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003100 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003101 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003102 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003103 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3104 { # typedef int*const TYPEDEF; // first
3105 # int foo(TYPEDEF p); // const is optimized out
3106 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3107 if($BTAttr{"Name"}=~/</)
3108 {
3109 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3110 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3111 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003112 }
3113 }
3114 }
3115 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3116 }
3117 if(not $TypeAttr{"Size"})
3118 {
3119 if($TypeAttr{"Type"} eq "Pointer") {
3120 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3121 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003122 elsif($BTAttr{"Size"}) {
3123 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003124 }
3125 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003126 if(my $Algn = getAlgn($TypeId)) {
3127 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3128 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003129 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003130 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3131 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003132 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003133 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003134 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003135 { # typedef to "class Class"
3136 # should not be registered in TName_Tid
3137 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3138 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3139 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003140 }
3141 return %TypeAttr;
3142 }
3143}
3144
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003145sub getTreeVec($)
3146{
3147 my %Vector = ();
3148 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3149 {
3150 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3151 { # string length is N-1 because of the null terminator
3152 $Vector{$1} = $2;
3153 }
3154 }
3155 return \%Vector;
3156}
3157
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003158sub get_TemplateParam($$)
3159{
3160 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003161 return () if(not $Type_Id);
3162 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3163 return () if(not $NodeType);
3164 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003165 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003166 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003167 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003168 my $Num = getNodeIntCst($Type_Id);
3169 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003170 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003171 }
3172 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003173 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003174 }
3175 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003176 elsif($NodeType eq "string_cst") {
3177 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003178 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003179 elsif($NodeType eq "tree_vec")
3180 {
3181 my $Vector = getTreeVec($Type_Id);
3182 my @Params = ();
3183 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3184 {
3185 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3186 push(@Params, $P2);
3187 }
3188 }
3189 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003190 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003191 elsif($NodeType eq "parm_decl")
3192 {
3193 (getNameByInfo($Type_Id));
3194 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003195 else
3196 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003197 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003198 my $PName = $ParamAttr{"Name"};
3199 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003200 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003201 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003202 if($PName=~/\>/)
3203 {
3204 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003205 $PName = $Cover;
3206 }
3207 }
3208 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003209 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003210 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3211 # template<typename _Key, typename _Compare = std::less<_Key>
3212 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3213 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3214 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3215 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003216 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003217 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003218 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003219 }
3220}
3221
3222sub cover_stdcxx_typedef($)
3223{
3224 my $TypeName = $_[0];
3225 if(my @Covers = sort {length($a)<=>length($b)}
3226 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3227 { # take the shortest typedef
3228 # FIXME: there may be more than
3229 # one typedefs to the same type
3230 return $Covers[0];
3231 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003232 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003233 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3234 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3235 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003236 if(my $Cover = $Covers[0])
3237 {
3238 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3239 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3240 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003241 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003242 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003243}
3244
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003245sub getNodeIntCst($)
3246{
3247 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003248 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003249 if($EnumMembName_Id{$Version}{$CstId}) {
3250 return $EnumMembName_Id{$Version}{$CstId};
3251 }
3252 elsif((my $Value = getTreeValue($CstId)) ne "")
3253 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003254 if($Value eq "0")
3255 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003256 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003257 return "false";
3258 }
3259 else {
3260 return "0";
3261 }
3262 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003263 elsif($Value eq "1")
3264 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003265 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003266 return "true";
3267 }
3268 else {
3269 return "1";
3270 }
3271 }
3272 else {
3273 return $Value;
3274 }
3275 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003276 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003277}
3278
3279sub getNodeStrCst($)
3280{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003281 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3282 {
3283 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003284 {
3285 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3286 { # string length is N-1 because of the null terminator
3287 return substr($1, 0, $2-1);
3288 }
3289 else
3290 { # identifier_node
3291 return substr($1, 0, $2);
3292 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003293 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003294 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003295 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003296}
3297
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003298sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003299{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003300 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003301 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3302 if($Type eq "FieldPtr") {
3303 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3304 }
3305 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3306 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003307 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003308 if($Type eq "MethodPtr")
3309 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003310 if(my $Size = getSize($TypeId))
3311 {
3312 $Size/=$BYTE_SIZE;
3313 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003314 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003315 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003316 if(my $Algn = getAlgn($TypeId)) {
3317 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003319 # Return
3320 if($Type eq "FieldPtr")
3321 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003322 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003323 if($ReturnAttr{"Name"}) {
3324 $MemPtrName .= $ReturnAttr{"Name"};
3325 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003326 $TypeAttr{"Return"} = $PtrId;
3327 }
3328 else
3329 {
3330 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3331 {
3332 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003333 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3334 if(not $ReturnAttr{"Name"})
3335 { # templates
3336 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003337 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003338 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003339 $TypeAttr{"Return"} = $ReturnTypeId;
3340 }
3341 }
3342 # Class
3343 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3344 {
3345 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003346 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003347 if($Class{"Name"}) {
3348 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3349 }
3350 else {
3351 $MemPtrName .= " (*)";
3352 }
3353 }
3354 else {
3355 $MemPtrName .= " (*)";
3356 }
3357 # Parameters
3358 if($Type eq "FuncPtr"
3359 or $Type eq "MethodPtr")
3360 {
3361 my @ParamTypeName = ();
3362 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3363 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003364 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003365 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003366 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003367 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003368 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3369 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003370 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003371 my $PTypeId = $1;
3372 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003373 if(not $ParamAttr{"Name"})
3374 { # templates (template_type_parm), etc.
3375 return ();
3376 }
3377 if($ParamAttr{"Name"} eq "void") {
3378 last;
3379 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003380 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003381 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003382 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003383 push(@ParamTypeName, $ParamAttr{"Name"});
3384 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003385 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3386 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003387 }
3388 else {
3389 last;
3390 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003391 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003392 else {
3393 last;
3394 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003395 }
3396 }
3397 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3398 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003399 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003400 return %TypeAttr;
3401}
3402
3403sub getTreeTypeName($)
3404{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003405 my $TypeId = $_[0];
3406 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003407 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003408 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003409 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003410 if(my $Name = getNameByInfo($TypeId))
3411 { # bit_size_type
3412 return $Name;
3413 }
3414 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003415 return "unsigned int";
3416 }
3417 else {
3418 return "int";
3419 }
3420 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003421 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003422 return getNameByInfo($1);
3423 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003424 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003425 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003426}
3427
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003428sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003429{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003430 my $Ptd = pointTo($_[0]);
3431 return 0 if(not $Ptd);
3432 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003433 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003434 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3435 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003436 }
3437 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003438 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3439 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003440 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003441 if($InfoT1 eq "pointer_type"
3442 and $InfoT2 eq "function_type") {
3443 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003444 }
3445 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003446 return 0;
3447}
3448
3449sub isMethodPtr($)
3450{
3451 my $Ptd = pointTo($_[0]);
3452 return 0 if(not $Ptd);
3453 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3454 {
3455 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3456 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3457 and $Info=~/ ptrmem /) {
3458 return 1;
3459 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003460 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003461 return 0;
3462}
3463
3464sub isFieldPtr($)
3465{
3466 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3467 {
3468 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3469 and $Info=~/ ptrmem /) {
3470 return 1;
3471 }
3472 }
3473 return 0;
3474}
3475
3476sub pointTo($)
3477{
3478 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3479 {
3480 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3481 return $1;
3482 }
3483 }
3484 return "";
3485}
3486
3487sub getTypeTypeByTypeId($)
3488{
3489 my $TypeId = $_[0];
3490 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3491 {
3492 my $NType = $NodeType{$TType};
3493 if($NType eq "Intrinsic") {
3494 return $NType;
3495 }
3496 elsif(isFuncPtr($TypeId)) {
3497 return "FuncPtr";
3498 }
3499 elsif(isMethodPtr($TypeId)) {
3500 return "MethodPtr";
3501 }
3502 elsif(isFieldPtr($TypeId)) {
3503 return "FieldPtr";
3504 }
3505 elsif($NType ne "Other") {
3506 return $NType;
3507 }
3508 }
3509 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003510}
3511
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003512my %UnQual = (
3513 "r"=>"restrict",
3514 "v"=>"volatile",
3515 "c"=>"const",
3516 "cv"=>"const volatile"
3517);
3518
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003519sub getQual($)
3520{
3521 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003522 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3523 {
3524 my ($Qual, $To) = ();
3525 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3526 $Qual = $UnQual{$1};
3527 }
3528 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3529 $To = $1;
3530 }
3531 if($Qual and $To) {
3532 return ($Qual, $To);
3533 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003534 }
3535 return ();
3536}
3537
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003538sub getQualType($)
3539{
3540 if($_[0] eq "const volatile") {
3541 return "ConstVolatile";
3542 }
3543 return ucfirst($_[0]);
3544}
3545
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003546sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003547{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003548 my $TypeId = $_[0];
3549 my $TypeDeclId = getTypeDeclId($TypeId);
3550 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003551 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003552 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3553 return "Typedef";
3554 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003555 }
3556 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3557 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003558 if(($Qual or $To) and $TypeDeclId
3559 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003560 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003561 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003562 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003563 elsif(not $MissedBase_R{$Version}{$TypeId}
3564 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003565 return "Typedef";
3566 }
3567 elsif($Qual)
3568 { # qualified types
3569 return getQualType($Qual);
3570 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003571
3572 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3573 { # typedef struct { ... } name
3574 $TypeTypedef{$Version}{$TypeId} = $1;
3575 }
3576
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003577 my $TypeType = getTypeTypeByTypeId($TypeId);
3578 if($TypeType eq "Struct")
3579 {
3580 if($TypeDeclId
3581 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3582 return "Template";
3583 }
3584 }
3585 return $TypeType;
3586}
3587
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003588sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003589{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003590 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003591 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003592 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3593 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3594 return 0;
3595 }
3596 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3597 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003598 if(my $TDid = getTypeDeclId($_[0]))
3599 {
3600 if(getTypeId($TDid) eq $_[0]
3601 and getNameByInfo($TDid))
3602 {
3603 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3604 return $1;
3605 }
3606 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003607 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003608 }
3609 }
3610 return 0;
3611}
3612
3613sub selectBaseType($)
3614{
3615 my $TypeId = $_[0];
3616 if(defined $MissedTypedef{$Version}{$TypeId})
3617 { # add missed typedefs
3618 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3619 return ($TypeId, "");
3620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003621 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003622 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3623 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003624
3625 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3626 my $MB = $MissedBase{$Version}{$TypeId};
3627
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003628 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003629 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003630 and (getTypeId($1) ne $TypeId)
3631 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003632 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003633 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003634 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003635 elsif($MB)
3636 { # add base
3637 return ($MB, "");
3638 }
3639 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003640 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003641 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003642 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003643 elsif($Qual or $To)
3644 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003645 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003646 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003647 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003648 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003649 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003650 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003652 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003653 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003654 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003655 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003656 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003657 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003658 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003659 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003660 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003661 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003662 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003663 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003664 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003665
3666 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003667}
3668
3669sub getSymbolInfo_All()
3670{
3671 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3672 { # reverse order
3673 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003674 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003675 }
3676 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003677
3678 if($ADD_TMPL_INSTANCES)
3679 {
3680 # templates
3681 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3682 {
3683 my %Map = ();
3684
3685 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3686 {
3687 if(defined $TemplateMap{$Version}{$ClassId})
3688 {
3689 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3690 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3691 }
3692 }
3693 }
3694
3695 if(defined $TemplateMap{$Version}{$Sid})
3696 {
3697 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3698 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3699 }
3700 }
3701
3702 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3703 {
3704 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3705 {
3706 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3707 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3708 }
3709 }
3710 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3711 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3712 }
3713 }
3714 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003715}
3716
3717sub getVarInfo_All()
3718{
3719 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3720 { # reverse order
3721 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003722 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003723 }
3724 }
3725}
3726
3727sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003728 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003729}
3730
3731sub getVarInfo($)
3732{
3733 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003734 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003735 {
3736 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3737 if($NSInfoType and $NSInfoType eq "function_decl") {
3738 return;
3739 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003740 }
3741 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3742 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3743 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3744 delete($SymbolInfo{$Version}{$InfoId});
3745 return;
3746 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003747 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003748 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003749 delete($SymbolInfo{$Version}{$InfoId});
3750 return;
3751 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003752 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3753 delete($SymbolInfo{$Version}{$InfoId});
3754 return;
3755 }
3756 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003757 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3758 {
3759 if($OSgroup eq "windows")
3760 { # cut the offset
3761 $MnglName=~s/\@\d+\Z//g;
3762 }
3763 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3764 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003765 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003766 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003767 { # validate mangled name
3768 delete($SymbolInfo{$Version}{$InfoId});
3769 return;
3770 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003771 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003772 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003773 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003774 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003775 }
3776 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3777 { # non-public global data
3778 delete($SymbolInfo{$Version}{$InfoId});
3779 return;
3780 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003781 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003782 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003783 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003784 if(not defined $TypeInfo{$Version}{$Rid}
3785 or not $TypeInfo{$Version}{$Rid}{"Name"})
3786 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003787 delete($SymbolInfo{$Version}{$InfoId});
3788 return;
3789 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003790 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3791 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003792 if(defined $Val) {
3793 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003795 }
3796 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003797 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3798 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003799 if(not defined $TypeInfo{$Version}{$ClassId}
3800 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3801 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003802 delete($SymbolInfo{$Version}{$InfoId});
3803 return;
3804 }
3805 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003806 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3807 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003808 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003809 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003810 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003811 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003812 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003813 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003814 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003815 if(not $CheckHeadersOnly)
3816 {
3817 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3818 {
3819 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3820 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3821 {
3822 if(link_symbol($ShortName, $Version, "-Deps"))
3823 { # "const" global data is mangled as _ZL... in the TU dump
3824 # but not mangled when compiling a C shared library
3825 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3826 }
3827 }
3828 }
3829 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003830 if($COMMON_LANGUAGE{$Version} eq "C++")
3831 {
3832 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3833 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003834 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003835 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3836 }
3837 }
3838 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3839 { # try to mangle symbol (link with libraries)
3840 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3841 }
3842 if($OStarget eq "windows")
3843 {
3844 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3845 { # link MS C++ symbols from library with GCC symbols from headers
3846 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3847 }
3848 }
3849 }
3850 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3851 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3852 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003853 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3854 {
3855 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3856 { # non-target symbols
3857 delete($SymbolInfo{$Version}{$InfoId});
3858 return;
3859 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003860 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003861 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3862 {
3863 if(defined $MissedTypedef{$Version}{$Rid})
3864 {
3865 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3866 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3867 }
3868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003869 }
3870 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003871 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003872 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3873 }
3874 if($ShortName=~/\A(_Z|\?)/) {
3875 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3876 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003877
3878 if($ExtraDump) {
3879 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003881}
3882
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003883sub isConstType($$)
3884{
3885 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003886 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003887 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003888 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003889 }
3890 return ($Base{"Type"} eq "Const");
3891}
3892
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003893sub getTrivialName($$)
3894{
3895 my ($TypeInfoId, $TypeId) = @_;
3896 my %TypeAttr = ();
3897 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3898 if(not $TypeAttr{"Name"}) {
3899 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3900 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003901 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003902 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003903 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003904 if(isAnon($TypeAttr{"Name"}))
3905 {
3906 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003907 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003908 { # searching for a first not anon scope
3909 if($NSId eq $NameSpaceId) {
3910 last;
3911 }
3912 else
3913 {
3914 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3915 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003916 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003917 last;
3918 }
3919 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003920 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003921 }
3922 }
3923 else
3924 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003925 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003926 {
3927 if($NameSpaceId ne $TypeId) {
3928 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3929 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003930 }
3931 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003932 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003933 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3934 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003935 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003936 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003937 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003938 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003939 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003940 if($TypeAttr{"NameSpace"}) {
3941 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003943 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003944 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3945 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003946 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003947 my @TParams = getTParams($TypeId, "Type");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003948 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003949 }
3950 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3951}
3952
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003953sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003954{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003955 my $TypeId = $_[0];
3956 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003957
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003958 my %TypeAttr = ();
3959
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003960 if($TemplateDecl{$Version}{$TypeId})
3961 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003962 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003963 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003964
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003965 setTypeAccess($TypeId, \%TypeAttr);
3966 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3967 if(isBuiltIn($TypeAttr{"Header"}))
3968 {
3969 delete($TypeAttr{"Header"});
3970 delete($TypeAttr{"Line"});
3971 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003972 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003973 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3974 if(not $TypeAttr{"Name"}) {
3975 return ();
3976 }
3977 if(not $TypeAttr{"NameSpace"}) {
3978 delete($TypeAttr{"NameSpace"});
3979 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003980
3981 my $Tmpl = undef;
3982
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003983 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003984 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003985 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3986
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003987 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003988 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003989 foreach my $Pos (0 .. $#TParams)
3990 {
3991 my $Val = $TParams[$Pos];
3992 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3993
3994 if(not defined $TypeAttr{"Template"})
3995 {
3996 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3997
3998 if($Base{"Type"} eq "TemplateParam"
3999 or defined $Base{"Template"}) {
4000 $TypeAttr{"Template"} = 1;
4001 }
4002 }
4003
4004 if($Tmpl)
4005 {
4006 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
4007 {
4008 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
4009
4010 if($Val eq $Arg) {
4011 $TypeAttr{"Template"} = 1;
4012 }
4013 }
4014 }
4015 }
4016
4017 if($Tmpl)
4018 {
4019 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
4020 {
4021 if($Pos>$#TParams)
4022 {
4023 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
4024 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
4025 }
4026 }
4027 }
4028 }
4029
4030 if($ADD_TMPL_INSTANCES)
4031 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004032 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004033 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004034 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004035 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004036 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004037 {
4038 if(my $Flds = getTreeAttr_Flds($MainInst)) {
4039 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
4040 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004041 }
4042 if(not getTreeAttr_Binf($TypeId))
4043 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004044 if(my $Binf = getTreeAttr_Binf($MainInst)) {
4045 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
4046 }
4047 }
4048 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004049 }
4050 }
4051 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004052
4053 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
4054
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004055 if(my $Size = getSize($TypeId))
4056 {
4057 $Size = $Size/$BYTE_SIZE;
4058 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004059 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004060 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004061 {
4062 if($ExtraDump)
4063 {
4064 if(not defined $TypeAttr{"Memb"}
4065 and not $Tmpl)
4066 { # declaration only
4067 $TypeAttr{"Forward"} = 1;
4068 }
4069 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004070 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004071
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004072 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004073 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004074 {
4075 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004076 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004077 }
4078 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004079 or $TypeAttr{"Type"} eq "Class")
4080 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004081 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004082 if($Skip) {
4083 return ();
4084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004085 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004086 if(my $Algn = getAlgn($TypeId)) {
4087 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4088 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004089 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004090
4091 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4092 {
4093 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004094 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004095 {
4096 if(not isAnon($TypeAttr{"Name"})) {
4097 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4098 }
4099 }
4100 }
4101
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004102 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004103 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4104 {
4105 my @Entries = split(/\n/, $VTable);
4106 foreach (1 .. $#Entries)
4107 {
4108 my $Entry = $Entries[$_];
4109 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004110 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004111 }
4112 }
4113 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004114
4115 if($TypeAttr{"Type"} eq "Enum")
4116 {
4117 if(not $TypeAttr{"NameSpace"})
4118 {
4119 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4120 {
4121 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004122 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004123 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004124 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004125 "Header"=>$TypeAttr{"Header"}
4126 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004127 if(isAnon($TypeAttr{"Name"}))
4128 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004129 if($ExtraDump
4130 or is_target_header($TypeAttr{"Header"}, $Version))
4131 {
4132 %{$Constants{$Version}{$MName}} = (
4133 "Value" => $MVal,
4134 "Header" => $TypeAttr{"Header"}
4135 );
4136 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004137 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004138 }
4139 }
4140 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004141 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004142 {
4143 if(defined $TypedefToAnon{$TypeId}) {
4144 $TypeAttr{"AnonTypedef"} = 1;
4145 }
4146 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004147
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004148 return %TypeAttr;
4149}
4150
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004151sub simplifyVTable($)
4152{
4153 my $Content = $_[0];
4154 if($Content=~s/ \[with (.+)]//)
4155 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4156 if(my @Elems = separate_Params($1, 0, 0))
4157 {
4158 foreach my $Elem (@Elems)
4159 {
4160 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4161 {
4162 my ($Arg, $Val) = ($1, $2);
4163
4164 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4165 $Content=~s/,\s*$Arg\b//g;
4166 }
4167 else {
4168 $Content=~s/\b$Arg\b/$Val/g;
4169 }
4170 }
4171 }
4172 }
4173 }
4174
4175 return $Content;
4176}
4177
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004178sub detect_lang($)
4179{
4180 my $TypeId = $_[0];
4181 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004182 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004183 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004184 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4185 }
4186 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004187 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004188 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004189 while($Fncs)
4190 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004191 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004192 return 1;
4193 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004194 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004195 }
4196 }
4197 return 0;
4198}
4199
4200sub setSpec($$)
4201{
4202 my ($TypeId, $TypeAttr) = @_;
4203 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4204 if($Info=~/\s+spec\s+/) {
4205 $TypeAttr->{"Spec"} = 1;
4206 }
4207}
4208
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004209sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004210{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004211 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004212 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004213 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004214 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004215 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004216 my $Pos = 0;
4217 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4218 {
4219 my ($Access, $BInfoId) = ($1, $2);
4220 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004221 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4222 if(not $CType or $CType eq "template_type_parm"
4223 or $CType eq "typename_type")
4224 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004225 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004226 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004227 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004228 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004229 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4230 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004231 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004232 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4233 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004234 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004235 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004236 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004237 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4238 }
4239 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004240 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004241 }
4242 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004243 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004244}
4245
4246sub getBinfClassId($)
4247{
4248 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4249 $Info=~/type[ ]*:[ ]*@(\d+) /;
4250 return $1;
4251}
4252
4253sub unmangledFormat($$)
4254{
4255 my ($Name, $LibVersion) = @_;
4256 $Name = uncover_typedefs($Name, $LibVersion);
4257 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4258 $Name=~s/\(\w+\)(\d)/$1/;
4259 return $Name;
4260}
4261
4262sub modelUnmangled($$)
4263{
4264 my ($InfoId, $Compiler) = @_;
4265 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4266 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4267 }
4268 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4269 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4270 $PureSignature = "~".$PureSignature;
4271 }
4272 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4273 {
4274 my (@Params, @ParamTypes) = ();
4275 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4276 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4277 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4278 }
4279 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4280 { # checking parameters
4281 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004282 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004283 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004284 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004285 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004286 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004287 }
4288 @ParamTypes = (@ParamTypes, $PTName);
4289 }
4290 if(@ParamTypes) {
4291 $PureSignature .= "(".join(", ", @ParamTypes).")";
4292 }
4293 else
4294 {
4295 if($Compiler eq "MSVC")
4296 {
4297 $PureSignature .= "(void)";
4298 }
4299 else
4300 { # GCC
4301 $PureSignature .= "()";
4302 }
4303 }
4304 $PureSignature = delete_keywords($PureSignature);
4305 }
4306 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4307 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004308 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004309 $PureSignature = $ClassName."::".$PureSignature;
4310 }
4311 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4312 $PureSignature = $NS."::".$PureSignature;
4313 }
4314 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4315 $PureSignature .= " const";
4316 }
4317 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4318 $PureSignature .= " volatile";
4319 }
4320 my $ShowReturn = 0;
4321 if($Compiler eq "MSVC"
4322 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4323 {
4324 $ShowReturn=1;
4325 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004326 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4327 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004328 {
4329 $ShowReturn=1;
4330 }
4331 if($ShowReturn)
4332 { # mangled names for template function specializations include return value
4333 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4334 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004335 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004336 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4337 $PureSignature = $ReturnName." ".$PureSignature;
4338 }
4339 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004340 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004341}
4342
4343sub mangle_symbol($$$)
4344{ # mangling for simple methods
4345 # see gcc-4.6.0/gcc/cp/mangle.c
4346 my ($InfoId, $LibVersion, $Compiler) = @_;
4347 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4348 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4349 }
4350 my $Mangled = "";
4351 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004352 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004353 }
4354 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004355 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004356 }
4357 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4358}
4359
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004360sub mangle_symbol_MSVC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004361{
4362 my ($InfoId, $LibVersion) = @_;
4363 return "";
4364}
4365
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004366sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004367{ # see gcc-4.6.0/gcc/cp/mangle.c
4368 my ($InfoId, $LibVersion) = @_;
4369 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004370 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004371 my %Repl = ();# SN_ replacements
4372 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4373 {
4374 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4375 if($MangledClass!~/\AN/) {
4376 $MangledClass = "N".$MangledClass;
4377 }
4378 else {
4379 $MangledClass=~s/E\Z//;
4380 }
4381 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4382 $MangledClass=~s/\AN/NV/;
4383 }
4384 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4385 $MangledClass=~s/\AN/NK/;
4386 }
4387 $Mangled .= $MangledClass;
4388 }
4389 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4390 { # mangled by name due to the absence of structured info
4391 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4392 if($MangledNS!~/\AN/) {
4393 $MangledNS = "N".$MangledNS;
4394 }
4395 else {
4396 $MangledNS=~s/E\Z//;
4397 }
4398 $Mangled .= $MangledNS;
4399 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004400 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004401 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004402 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004403 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004404 foreach (@TPos) {
4405 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4406 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004407 }
4408 elsif($TmplParams)
4409 { # remangling mode
4410 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004411 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004412 }
4413 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4414 $Mangled .= "C1";
4415 }
4416 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4417 $Mangled .= "D0";
4418 }
4419 elsif($ShortName)
4420 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004421 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4422 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004423 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004424 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004425 { # "const" global data is mangled as _ZL...
4426 $Mangled .= "L";
4427 }
4428 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004429 if($ShortName=~/\Aoperator(\W.*)\Z/)
4430 {
4431 my $Op = $1;
4432 $Op=~s/\A[ ]+//g;
4433 if(my $OpMngl = $OperatorMangling{$Op}) {
4434 $Mangled .= $OpMngl;
4435 }
4436 else { # conversion operator
4437 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4438 }
4439 }
4440 else {
4441 $Mangled .= length($ShortName).$ShortName;
4442 }
4443 if(@TParams)
4444 { # templates
4445 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004446 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004447 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4448 }
4449 $Mangled .= "E";
4450 }
4451 if(not $ClassId and @TParams) {
4452 add_substitution($ShortName, \%Repl, 0);
4453 }
4454 }
4455 if($ClassId or $NameSpace) {
4456 $Mangled .= "E";
4457 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004458 if(@TParams)
4459 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004460 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004461 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4462 }
4463 }
4464 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4465 {
4466 my @Params = ();
4467 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4468 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4469 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4470 }
4471 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4472 { # checking parameters
4473 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4474 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4475 }
4476 if(not @Params) {
4477 $Mangled .= "v";
4478 }
4479 }
4480 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4481 $Mangled = write_stdcxx_substitution($Mangled);
4482 if($Mangled eq "_Z") {
4483 return "";
4484 }
4485 return $Mangled;
4486}
4487
4488sub correct_incharge($$$)
4489{
4490 my ($InfoId, $LibVersion, $Mangled) = @_;
4491 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4492 {
4493 if($MangledNames{$LibVersion}{$Mangled}) {
4494 $Mangled=~s/C1E/C2E/;
4495 }
4496 }
4497 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4498 {
4499 if($MangledNames{$LibVersion}{$Mangled}) {
4500 $Mangled=~s/D0E/D1E/;
4501 }
4502 if($MangledNames{$LibVersion}{$Mangled}) {
4503 $Mangled=~s/D1E/D2E/;
4504 }
4505 }
4506 return $Mangled;
4507}
4508
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004509sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004510{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004511 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004512 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004513 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004514 return $Name;
4515 }
4516 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004517 while(my $CPos = find_center($TParams, "<"))
4518 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004519 $TParams = substr($TParams, $CPos);
4520 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004521 if($TParams=~s/\A<(.+)>\Z/$1/) {
4522 $Name=~s/<\Q$TParams\E>\Z//;
4523 }
4524 else
4525 { # error
4526 $TParams = "";
4527 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004528 return ($Name, $TParams);
4529}
4530
4531sub get_sub_ns($)
4532{
4533 my $Name = $_[0];
4534 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004535 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004536 {
4537 push(@NS, substr($Name, 0, $CPos));
4538 $Name = substr($Name, $CPos);
4539 $Name=~s/\A:://;
4540 }
4541 return (join("::", @NS), $Name);
4542}
4543
4544sub mangle_ns($$$)
4545{
4546 my ($Name, $LibVersion, $Repl) = @_;
4547 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4548 {
4549 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4550 $Mangled=~s/\AN(.+)E\Z/$1/;
4551 return $Mangled;
4552
4553 }
4554 else
4555 {
4556 my ($MangledNS, $SubNS) = ("", "");
4557 ($SubNS, $Name) = get_sub_ns($Name);
4558 if($SubNS) {
4559 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4560 }
4561 $MangledNS .= length($Name).$Name;
4562 add_substitution($MangledNS, $Repl, 0);
4563 return $MangledNS;
4564 }
4565}
4566
4567sub mangle_param($$$)
4568{
4569 my ($PTid, $LibVersion, $Repl) = @_;
4570 my ($MPrefix, $Mangled) = ("", "");
4571 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004572 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004573 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004574 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004575 if(not $BaseType_Name) {
4576 return "";
4577 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004578 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004579 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004580 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4581 while($Suffix=~/(&|\*|const)\Z/)
4582 {
4583 if($Suffix=~s/[ ]*&\Z//) {
4584 $MPrefix .= "R";
4585 }
4586 if($Suffix=~s/[ ]*\*\Z//) {
4587 $MPrefix .= "P";
4588 }
4589 if($Suffix=~s/[ ]*const\Z//)
4590 {
4591 if($MPrefix=~/R|P/
4592 or $Suffix=~/&|\*/) {
4593 $MPrefix .= "K";
4594 }
4595 }
4596 if($Suffix=~s/[ ]*volatile\Z//) {
4597 $MPrefix .= "V";
4598 }
4599 #if($Suffix=~s/[ ]*restrict\Z//) {
4600 #$MPrefix .= "r";
4601 #}
4602 }
4603 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4604 $Mangled .= $Token;
4605 }
4606 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4607 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004608 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004609 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004610 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004611 foreach (@TPos) {
4612 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4613 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004614 }
4615 elsif($TmplParams)
4616 { # remangling mode
4617 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004618 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004619 }
4620 my $MangledNS = "";
4621 my ($SubNS, $SName) = get_sub_ns($ShortName);
4622 if($SubNS) {
4623 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4624 }
4625 $MangledNS .= length($SName).$SName;
4626 if(@TParams) {
4627 add_substitution($MangledNS, $Repl, 0);
4628 }
4629 $Mangled .= "N".$MangledNS;
4630 if(@TParams)
4631 { # templates
4632 $Mangled .= "I";
4633 foreach my $TParam (@TParams) {
4634 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4635 }
4636 $Mangled .= "E";
4637 }
4638 $Mangled .= "E";
4639 }
4640 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4641 {
4642 if($BaseType{"Type"} eq "MethodPtr") {
4643 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4644 }
4645 else {
4646 $Mangled .= "PF";
4647 }
4648 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4649 my @Params = keys(%{$BaseType{"Param"}});
4650 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4651 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4652 }
4653 if(not @Params) {
4654 $Mangled .= "v";
4655 }
4656 $Mangled .= "E";
4657 }
4658 elsif($BaseType{"Type"} eq "FieldPtr")
4659 {
4660 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4661 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4662 }
4663 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4664 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4665 {
4666 if($Mangled eq $Optimized)
4667 {
4668 if($ShortName!~/::/)
4669 { # remove "N ... E"
4670 if($MPrefix) {
4671 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4672 }
4673 else {
4674 $Mangled=~s/\AN(.+)E\Z/$1/g;
4675 }
4676 }
4677 }
4678 else {
4679 $Mangled = $Optimized;
4680 }
4681 }
4682 add_substitution($Mangled, $Repl, 1);
4683 return $Mangled;
4684}
4685
4686sub mangle_template_param($$$)
4687{ # types + literals
4688 my ($TParam, $LibVersion, $Repl) = @_;
4689 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4690 return mangle_param($TPTid, $LibVersion, $Repl);
4691 }
4692 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4693 { # class_name<1u>::method(...)
4694 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4695 }
4696 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4697 { # class_name<(signed char)1>::method(...)
4698 return "L".$IntrinsicMangling{$1}.$2."E";
4699 }
4700 elsif($TParam eq "true")
4701 { # class_name<true>::method(...)
4702 return "Lb1E";
4703 }
4704 elsif($TParam eq "false")
4705 { # class_name<true>::method(...)
4706 return "Lb0E";
4707 }
4708 else { # internal error
4709 return length($TParam).$TParam;
4710 }
4711}
4712
4713sub add_substitution($$$)
4714{
4715 my ($Value, $Repl, $Rec) = @_;
4716 if($Rec)
4717 { # subtypes
4718 my @Subs = ($Value);
4719 while($Value=~s/\A(R|P|K)//) {
4720 push(@Subs, $Value);
4721 }
4722 foreach (reverse(@Subs)) {
4723 add_substitution($_, $Repl, 0);
4724 }
4725 return;
4726 }
4727 return if($Value=~/\AS(\d*)_\Z/);
4728 $Value=~s/\AN(.+)E\Z/$1/g;
4729 return if(defined $Repl->{$Value});
4730 return if(length($Value)<=1);
4731 return if($StdcxxMangling{$Value});
4732 # check for duplicates
4733 my $Base = $Value;
4734 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4735 {
4736 my $Num = $Repl->{$Type};
4737 my $Replace = macro_mangle($Num);
4738 $Base=~s/\Q$Replace\E/$Type/;
4739 }
4740 if(my $OldNum = $Repl->{$Base})
4741 {
4742 $Repl->{$Value} = $OldNum;
4743 return;
4744 }
4745 my @Repls = sort {$b<=>$a} values(%{$Repl});
4746 if(@Repls) {
4747 $Repl->{$Value} = $Repls[0]+1;
4748 }
4749 else {
4750 $Repl->{$Value} = -1;
4751 }
4752 # register duplicates
4753 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004754 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004755 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4756 {
4757 next if($Base eq $Type);
4758 my $Num = $Repl->{$Type};
4759 my $Replace = macro_mangle($Num);
4760 $Base=~s/\Q$Type\E/$Replace/;
4761 $Repl->{$Base} = $Repl->{$Value};
4762 }
4763}
4764
4765sub macro_mangle($)
4766{
4767 my $Num = $_[0];
4768 if($Num==-1) {
4769 return "S_";
4770 }
4771 else
4772 {
4773 my $Code = "";
4774 if($Num<10)
4775 { # S0_, S1_, S2_, ...
4776 $Code = $Num;
4777 }
4778 elsif($Num>=10 and $Num<=35)
4779 { # SA_, SB_, SC_, ...
4780 $Code = chr(55+$Num);
4781 }
4782 else
4783 { # S10_, S11_, S12_
4784 $Code = $Num-26; # 26 is length of english alphabet
4785 }
4786 return "S".$Code."_";
4787 }
4788}
4789
4790sub write_stdcxx_substitution($)
4791{
4792 my $Mangled = $_[0];
4793 if($StdcxxMangling{$Mangled}) {
4794 return $StdcxxMangling{$Mangled};
4795 }
4796 else
4797 {
4798 my @Repls = keys(%StdcxxMangling);
4799 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4800 foreach my $MangledType (@Repls)
4801 {
4802 my $Replace = $StdcxxMangling{$MangledType};
4803 #if($Mangled!~/$Replace/) {
4804 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4805 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4806 #}
4807 }
4808 }
4809 return $Mangled;
4810}
4811
4812sub write_substitution($$)
4813{
4814 my ($Mangled, $Repl) = @_;
4815 if(defined $Repl->{$Mangled}
4816 and my $MnglNum = $Repl->{$Mangled}) {
4817 $Mangled = macro_mangle($MnglNum);
4818 }
4819 else
4820 {
4821 my @Repls = keys(%{$Repl});
4822 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4823 # FIXME: how to apply replacements? by num or by pos
4824 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4825 foreach my $MangledType (@Repls)
4826 {
4827 my $Replace = macro_mangle($Repl->{$MangledType});
4828 if($Mangled!~/$Replace/) {
4829 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4830 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4831 }
4832 }
4833 }
4834 return $Mangled;
4835}
4836
4837sub delete_keywords($)
4838{
4839 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004840 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004841 return $TypeName;
4842}
4843
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004844sub uncover_typedefs($$)
4845{
4846 my ($TypeName, $LibVersion) = @_;
4847 return "" if(not $TypeName);
4848 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4849 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4850 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004851 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004852 while($TypeName_New ne $TypeName_Pre)
4853 {
4854 $TypeName_Pre = $TypeName_New;
4855 my $TypeName_Copy = $TypeName_New;
4856 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004857 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004858 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004859 if(not $Intrinsic_Keywords{$1}) {
4860 $Words{$1} = 1;
4861 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004862 }
4863 foreach my $Word (keys(%Words))
4864 {
4865 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4866 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004867 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004868 if($BaseType_Name=~/\([\*]+\)/)
4869 { # FuncPtr
4870 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4871 {
4872 my $Type_Suffix = $1;
4873 $TypeName_New = $BaseType_Name;
4874 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004875 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004876 }
4877 }
4878 }
4879 else
4880 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004881 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004882 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004883 }
4884 }
4885 }
4886 }
4887 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4888}
4889
4890sub isInternal($)
4891{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004892 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4893 {
4894 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4895 {
4896 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4897 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4898 return 1;
4899 }
4900 }
4901 }
4902 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004903}
4904
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004905sub getDataVal($$)
4906{
4907 my ($InfoId, $TypeId) = @_;
4908 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4909 {
4910 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4911 {
4912 if(defined $LibInfo{$Version}{"info_type"}{$1}
4913 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004914 {
4915 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004916 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004917 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4918 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004919 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004920 if(my $Addr = getTreeAttr_Op($1)) {
4921 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004922 }
4923 }
4924 }
4925 }
4926 else {
4927 return getInitVal($1, $TypeId);
4928 }
4929 }
4930 }
4931 return undef;
4932}
4933
4934sub getInitVal($$)
4935{
4936 my ($InfoId, $TypeId) = @_;
4937 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4938 {
4939 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4940 {
4941 if($InfoType eq "integer_cst")
4942 {
4943 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004944 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004945 { # characters
4946 $Val = chr($Val);
4947 }
4948 return $Val;
4949 }
4950 elsif($InfoType eq "string_cst") {
4951 return getNodeStrCst($InfoId);
4952 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004953 elsif($InfoType eq "var_decl")
4954 {
4955 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4956 return $Name;
4957 }
4958 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004959 }
4960 }
4961 return undef;
4962}
4963
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004964sub set_Class_And_Namespace($)
4965{
4966 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004967 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004968 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004969 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004970 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004971 my $NSInfoId = $1;
4972 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4973 {
4974 if($InfoType eq "namespace_decl") {
4975 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4976 }
4977 elsif($InfoType eq "record_type") {
4978 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4979 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004980 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004981 }
4982 }
4983 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4984 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004985 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004986 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004987 { # skip
4988 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004990 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004991
4992 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004993}
4994
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004995sub debugMangling($)
4996{
4997 my $LibVersion = $_[0];
4998 my %Mangled = ();
4999 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
5000 {
5001 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
5002 {
5003 if($Mngl=~/\A(_Z|\?)/) {
5004 $Mangled{$Mngl}=$InfoId;
5005 }
5006 }
5007 }
5008 translateSymbols(keys(%Mangled), $LibVersion);
5009 foreach my $Mngl (keys(%Mangled))
5010 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005011 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
5012 my $U2 = $tr_name{$Mngl};
5013 if($U1 ne $U2) {
5014 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005015 }
5016 }
5017}
5018
5019sub linkSymbol($)
5020{ # link symbols from shared libraries
5021 # with the symbols from header files
5022 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005023 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005024 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
5025 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005026 { # 1. GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
5027 # 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 +04005028 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005029 {
5030 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
5031 return correct_incharge($InfoId, $Version, $Mangled);
5032 }
5033 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005034 if($CheckHeadersOnly
5035 or not $BinaryOnly)
5036 { # 1. --headers-only mode
5037 # 2. not mangled src-only symbols
5038 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
5039 return $Mangled;
5040 }
5041 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005042 }
5043 return "";
5044}
5045
5046sub setLanguage($$)
5047{
5048 my ($LibVersion, $Lang) = @_;
5049 if(not $UserLang) {
5050 $COMMON_LANGUAGE{$LibVersion} = $Lang;
5051 }
5052}
5053
5054sub getSymbolInfo($)
5055{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005056 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005057 if(isInternal($InfoId)) {
5058 return;
5059 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005060 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5061 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005062 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5063 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005064 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005065 return;
5066 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005067 setFuncAccess($InfoId);
5068 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005069 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5070 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005071 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005072 return;
5073 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005074
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005075 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005076 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005077 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005078 if(not defined $TypeInfo{$Version}{$Return}
5079 or not $TypeInfo{$Version}{$Return}{"Name"})
5080 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005081 delete($SymbolInfo{$Version}{$InfoId});
5082 return;
5083 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005084 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005085 }
5086 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5087 {
5088 if(defined $MissedTypedef{$Version}{$Rid})
5089 {
5090 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5091 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5092 }
5093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005094 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005095 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5096 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005097 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005098 my $Orig = getFuncOrig($InfoId);
5099 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005100 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5101 {
5102 delete($SymbolInfo{$Version}{$InfoId});
5103 return;
5104 }
5105
5106 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005107 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005108 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005109 return;
5110 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005111
5112 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005113 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005114 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5115
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005116 my @TParams = getTParams($Orig, "Func");
5117 if(not @TParams)
5118 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005119 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005120 return;
5121 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005122 foreach my $Pos (0 .. $#TParams)
5123 {
5124 my $Val = $TParams[$Pos];
5125 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5126
5127 if($Tmpl)
5128 {
5129 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5130 {
5131 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5132 }
5133 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005134 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005135
5136 if($Tmpl)
5137 {
5138 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5139 {
5140 if($Pos>$#TParams)
5141 {
5142 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5143 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5144 }
5145 }
5146 }
5147
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005148 my $PrmsInLine = join(", ", @TParams);
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005149 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5150 { # operator<< <T>, operator>> <T>
5151 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5152 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005153 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".$PrmsInLine.">";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005154 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005155 }
5156 else
5157 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005158 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005159 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005160 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5161 {
5162 if($OSgroup eq "windows")
5163 { # cut the offset
5164 $MnglName=~s/\@\d+\Z//g;
5165 }
5166 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5167
5168 # NOTE: mangling of some symbols may change depending on GCC version
5169 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5170 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5171 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005172
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005173 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005174 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005175 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005176 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005177 return;
5178 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005179 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005180 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005181 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005182 if($Skip)
5183 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005184 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005185 return;
5186 }
5187 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005188 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5189 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5190 }
5191
5192 if(set_Class_And_Namespace($InfoId))
5193 {
5194 delete($SymbolInfo{$Version}{$InfoId});
5195 return;
5196 }
5197
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005198 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5199 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005200 if(not defined $TypeInfo{$Version}{$ClassId}
5201 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5202 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005203 delete($SymbolInfo{$Version}{$InfoId});
5204 return;
5205 }
5206 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005207 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5208 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005209 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005210 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005211 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005212 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005213 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005214 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005215 }
5216 if($COMMON_LANGUAGE{$Version} eq "C++")
5217 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005218 # C++ or --headers-only mode
5219 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005220 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005221 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5222 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005223 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005224 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005225 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005226 if(my $Mangled = linkSymbol($InfoId)) {
5227 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005228 }
5229 }
5230 if($OStarget eq "windows")
5231 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005232 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005233 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005234 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005235 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005236 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005237 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005238 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005239 }
5240 }
5241 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005242 else
5243 { # not mangled in C
5244 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5245 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005246 if(not $CheckHeadersOnly
5247 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5248 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5249 {
5250 my $Incorrect = 0;
5251
5252 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5253 {
5254 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5255 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5256 { # mangled in the TU dump, but not mangled in the library
5257 $Incorrect = 1;
5258 }
5259 }
5260 else
5261 {
5262 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5263 { # all C++ functions are not mangled in the TU dump
5264 $Incorrect = 1;
5265 }
5266 }
5267 if($Incorrect)
5268 {
5269 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5270 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5271 }
5272 }
5273 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005274 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005275 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005276 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005277 return;
5278 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005279 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005280 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005281 { # identify virtual and pure virtual functions
5282 # NOTE: constructors cannot be virtual
5283 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5284 # in the TU dump, so taking it from the original symbol
5285 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5286 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5287 { # NOTE: D2 destructors are not present in a v-table
5288 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5289 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005290 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005291 if(isInline($InfoId)) {
5292 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005293 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005294 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005295 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5296 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005297 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5298 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005299 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005300 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005301 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005302 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005303 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005304 }
5305 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005306 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5307 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005308 if(not $ExtraDump)
5309 {
5310 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5311 { # non-target symbols
5312 delete($SymbolInfo{$Version}{$InfoId});
5313 return;
5314 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005315 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005316 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005317 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5318 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5319 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5320 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005321 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005322 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5323 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005324 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005325 return;
5326 }
5327 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005328 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005329 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005330 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005331 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005332 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005333 return;
5334 }
5335 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005336 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005337 }
5338 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005339 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5340 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5341 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005342 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005343 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5344 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005345 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005346 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005347 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005348 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005349 }
5350 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005351 if(getFuncLink($InfoId) eq "Static") {
5352 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005353 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005354 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5355 {
5356 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5357 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005358 if($Unmangled=~/\.\_\d/)
5359 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005360 delete($SymbolInfo{$Version}{$InfoId});
5361 return;
5362 }
5363 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005364 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005365 delete($SymbolInfo{$Version}{$InfoId}{"Type"});
5366 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5367 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005368 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005369 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5370 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005371 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005372
5373 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5374 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5375 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005376
5377 if($ExtraDump) {
5378 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5379 }
5380}
5381
5382sub guessHeader($)
5383{
5384 my $InfoId = $_[0];
5385 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5386 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5387 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5388 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5389 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5390 {
5391 if(get_filename($HPath) eq $Header)
5392 {
5393 my $HDir = get_filename(get_dirname($HPath));
5394 if($HDir ne "include"
5395 and $HDir=~/\A[a-z]+\Z/i) {
5396 return join_P($HDir, $Header);
5397 }
5398 }
5399 }
5400 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005401}
5402
5403sub isInline($)
5404{ # "body: undefined" in the tree
5405 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005406 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5407 {
5408 if($Info=~/ undefined /i) {
5409 return 0;
5410 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005411 }
5412 return 1;
5413}
5414
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005415sub hasThrow($)
5416{
5417 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5418 {
5419 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5420 return getTreeAttr_Unql($1, "unql");
5421 }
5422 }
5423 return 1;
5424}
5425
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005426sub getTypeId($)
5427{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005428 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5429 {
5430 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5431 return $1;
5432 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005433 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005434 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005435}
5436
5437sub setTypeMemb($$)
5438{
5439 my ($TypeId, $TypeAttr) = @_;
5440 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005441 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005442 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005443 if($TypeType eq "Enum")
5444 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005445 my $MInfoId = getTreeAttr_Csts($TypeId);
5446 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005447 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005448 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5449 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005450 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005451 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5452 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005453 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005454 }
5455 }
5456 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5457 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005458 my $MInfoId = getTreeAttr_Flds($TypeId);
5459 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005460 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005461 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5462 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005463 if(not $IType or $IType ne "field_decl")
5464 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005465
5466 if($IType eq "var_decl")
5467 { # static field
5468 $StaticFields = 1;
5469 }
5470
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005471 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005472 next;
5473 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005474 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005475 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005476 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005477 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005478 }
5479 if(not $StructMembName)
5480 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005481 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005482 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005483 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005484 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5485 if(isAnon($UnnamedTName))
5486 { # rename unnamed fields to unnamed0, unnamed1, ...
5487 $StructMembName = "unnamed".($UnnamedPos++);
5488 }
5489 }
5490 }
5491 if(not $StructMembName)
5492 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005493 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005494 next;
5495 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005496 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005497 if(defined $MissedTypedef{$Version}{$MembTypeId})
5498 {
5499 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5500 $MembTypeId = $AddedTid;
5501 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005502 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005503
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005504 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5505 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005506 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005507 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005508 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5509 }
5510 if($MInfo=~/spec:\s*mutable /)
5511 { # mutable fields
5512 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005513 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005514 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005515 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5516 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005517 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005518 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005519 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005520 }
5521 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005522 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005523 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5524 { # template
5525 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5526 }
5527 else {
5528 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5529 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005530 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005531
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005532 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005533 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005534 }
5535 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005536
5537 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005538}
5539
5540sub setFuncParams($)
5541{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005542 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005543 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005544 if(getFuncType($InfoId) eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005545 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005546 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5547 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005548 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005549 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005550 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5551 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005552 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005553 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5554 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005555 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005556 else
5557 { # skip
5558 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005559 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005560 # skip "this"-parameter
5561 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005562 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005563 my ($Pos, $Vtt_Pos) = (0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005564 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005565 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005566 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5567 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5568 if(not $ParamName)
5569 { # unnamed
5570 $ParamName = "p".($Pos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005571 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005572 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5573 {
5574 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5575 $ParamTypeId = $AddedTid;
5576 }
5577 }
5578 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005579 if(not $PType or $PType eq "Unknown") {
5580 return 1;
5581 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005582 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005583 if(not $PTName) {
5584 return 1;
5585 }
5586 if($PTName eq "void") {
5587 last;
5588 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005589 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005590 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005591 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005592 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005593 $ParamInfoId = getNextElem($ParamInfoId);
5594 next;
5595 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005596 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005597
5598 if(my %Base = get_BaseType($ParamTypeId, $Version))
5599 {
5600 if(defined $Base{"Template"}) {
5601 return 1;
5602 }
5603 }
5604
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005605 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005606 if(my $Algn = getAlgn($ParamInfoId)) {
5607 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5608 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005609 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"}) {
5610 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($Pos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005611 }
5612 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5613 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005614 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005615 }
5616 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005617 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005618 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005619 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005620 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005621 }
5622 return 0;
5623}
5624
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005625sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005626{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005627 my ($InfoId, $Vtt_Pos) = @_;
5628 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005629 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005630 if(getFuncType($InfoId) eq "Method") {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005631 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005632 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005633 if(not $ParamListElemId)
5634 { # foo(...)
5635 return 1;
5636 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005637 my $HaveVoid = 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005638 my $Pos = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005639 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005640 { # actual params: may differ from formal args
5641 # formal int*const
5642 # actual: int*
5643 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005644 {
5645 $Vtt_Pos=-1;
5646 $ParamListElemId = getNextElem($ParamListElemId);
5647 next;
5648 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005649 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5650 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005651 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005652 $HaveVoid = 1;
5653 last;
5654 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005655 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005656 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005657 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5658 {
5659 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5660 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5661 { # unnamed
5662 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($Pos+1);
5663 }
5664 }
5665 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5666 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005667 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005668 { # params
5669 if($OldId ne $ParamTypeId)
5670 {
5671 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5672 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5673
5674 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5675 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5676 }
5677 }
5678 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005679 }
5680 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005681 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005682 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005683 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5684 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005685 if($PurpType eq "nop_expr")
5686 { # func ( const char* arg = (const char*)(void*)0 )
5687 $PurpId = getTreeAttr_Op($PurpId);
5688 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005689 my $Val = getInitVal($PurpId, $ParamTypeId);
5690 if(defined $Val) {
5691 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005693 }
5694 }
5695 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005696 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005697 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005698 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005699}
5700
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005701sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005702{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005703 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5704 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005705 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5706 return $1;
5707 }
5708 }
5709 return "";
5710}
5711
5712sub getTreeAttr_Chain($)
5713{
5714 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5715 {
5716 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5717 return $1;
5718 }
5719 }
5720 return "";
5721}
5722
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005723sub getTreeAttr_Unql($)
5724{
5725 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5726 {
5727 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5728 return $1;
5729 }
5730 }
5731 return "";
5732}
5733
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005734sub getTreeAttr_Scpe($)
5735{
5736 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5737 {
5738 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5739 return $1;
5740 }
5741 }
5742 return "";
5743}
5744
5745sub getTreeAttr_Type($)
5746{
5747 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5748 {
5749 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5750 return $1;
5751 }
5752 }
5753 return "";
5754}
5755
5756sub getTreeAttr_Name($)
5757{
5758 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5759 {
5760 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5761 return $1;
5762 }
5763 }
5764 return "";
5765}
5766
5767sub getTreeAttr_Mngl($)
5768{
5769 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5770 {
5771 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5772 return $1;
5773 }
5774 }
5775 return "";
5776}
5777
5778sub getTreeAttr_Prms($)
5779{
5780 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5781 {
5782 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5783 return $1;
5784 }
5785 }
5786 return "";
5787}
5788
5789sub getTreeAttr_Fncs($)
5790{
5791 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5792 {
5793 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5794 return $1;
5795 }
5796 }
5797 return "";
5798}
5799
5800sub getTreeAttr_Csts($)
5801{
5802 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5803 {
5804 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5805 return $1;
5806 }
5807 }
5808 return "";
5809}
5810
5811sub getTreeAttr_Purp($)
5812{
5813 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5814 {
5815 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5816 return $1;
5817 }
5818 }
5819 return "";
5820}
5821
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005822sub getTreeAttr_Op($)
5823{
5824 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5825 {
5826 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5827 return $1;
5828 }
5829 }
5830 return "";
5831}
5832
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005833sub getTreeAttr_Valu($)
5834{
5835 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5836 {
5837 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5838 return $1;
5839 }
5840 }
5841 return "";
5842}
5843
5844sub getTreeAttr_Flds($)
5845{
5846 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5847 {
5848 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5849 return $1;
5850 }
5851 }
5852 return "";
5853}
5854
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005855sub getTreeAttr_Binf($)
5856{
5857 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5858 {
5859 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5860 return $1;
5861 }
5862 }
5863 return "";
5864}
5865
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005866sub getTreeAttr_Args($)
5867{
5868 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5869 {
5870 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005871 return $1;
5872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005873 }
5874 return "";
5875}
5876
5877sub getTreeValue($)
5878{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005879 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5880 {
5881 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5882 return $1;
5883 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005884 }
5885 return "";
5886}
5887
5888sub getTreeAccess($)
5889{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005890 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005891 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005892 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5893 {
5894 my $Access = $1;
5895 if($Access eq "prot") {
5896 return "protected";
5897 }
5898 elsif($Access eq "priv") {
5899 return "private";
5900 }
5901 }
5902 elsif($Info=~/ protected /)
5903 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005904 return "protected";
5905 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005906 elsif($Info=~/ private /)
5907 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005908 return "private";
5909 }
5910 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005911 return "public";
5912}
5913
5914sub setFuncAccess($)
5915{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005916 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005917 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005918 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005919 }
5920 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005921 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005922 }
5923}
5924
5925sub setTypeAccess($$)
5926{
5927 my ($TypeId, $TypeAttr) = @_;
5928 my $Access = getTreeAccess($TypeId);
5929 if($Access eq "protected") {
5930 $TypeAttr->{"Protected"} = 1;
5931 }
5932 elsif($Access eq "private") {
5933 $TypeAttr->{"Private"} = 1;
5934 }
5935}
5936
5937sub setFuncKind($)
5938{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005939 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5940 {
5941 if($Info=~/pseudo tmpl/) {
5942 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5943 }
5944 elsif($Info=~/ constructor /) {
5945 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5946 }
5947 elsif($Info=~/ destructor /) {
5948 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005950 }
5951}
5952
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005953sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005954{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005955 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5956 {
5957 if($Info=~/spec[ ]*:[ ]*pure /) {
5958 return "PureVirt";
5959 }
5960 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5961 return "Virt";
5962 }
5963 elsif($Info=~/ pure\s+virtual /)
5964 { # support for old GCC versions
5965 return "PureVirt";
5966 }
5967 elsif($Info=~/ virtual /)
5968 { # support for old GCC versions
5969 return "Virt";
5970 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005971 }
5972 return "";
5973}
5974
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005975sub getFuncLink($)
5976{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005977 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5978 {
5979 if($Info=~/link[ ]*:[ ]*static /) {
5980 return "Static";
5981 }
5982 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005983 return $1;
5984 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005985 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005986 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005987}
5988
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005989sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005990{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005991 my ($Symbol, $LibVersion) = @_;
5992 return "" if(not $Symbol or not $LibVersion);
5993 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5994 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005995 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005996 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5997 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5998 }
5999 }
6000 if($NS)
6001 {
6002 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6003 return $NS;
6004 }
6005 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006006 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006007 while($NS=~s/::[^:]+\Z//)
6008 {
6009 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6010 return $NS;
6011 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006012 }
6013 }
6014 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006015
6016 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006017}
6018
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006019sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006020{
6021 my ($TypeName, $LibVersion) = @_;
6022 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006023 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006024 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006025 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6026 return $NS;
6027 }
6028 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006029 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006030 while($NS=~s/::[^:]+\Z//)
6031 {
6032 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6033 return $NS;
6034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006035 }
6036 }
6037 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006038 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006039}
6040
6041sub getNameSpace($)
6042{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006043 my $InfoId = $_[0];
6044 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006045 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006046 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006047 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006048 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006049 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006050 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6051 {
6052 my $NameSpace = getTreeStr($1);
6053 if($NameSpace eq "::")
6054 { # global namespace
6055 return "";
6056 }
6057 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6058 $NameSpace = $BaseNameSpace."::".$NameSpace;
6059 }
6060 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6061 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006062 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006063 else {
6064 return "";
6065 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006066 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006067 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006068 { # inside data type
6069 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6070 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006071 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006072 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006073 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006074 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006075}
6076
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006077sub getEnumMembVal($)
6078{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006079 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006080 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006081 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6082 {
6083 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6084 {
6085 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6086 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6087 return getTreeValue($1);
6088 }
6089 else
6090 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6091 return getTreeValue($1);
6092 }
6093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006094 }
6095 }
6096 return "";
6097}
6098
6099sub getSize($)
6100{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006101 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6102 {
6103 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6104 return getTreeValue($1);
6105 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006106 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006107 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006108}
6109
6110sub getAlgn($)
6111{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006112 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6113 {
6114 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6115 return $1;
6116 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006117 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006118 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006119}
6120
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006121sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006122{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006123 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6124 {
6125 if($Info=~/ bitfield /) {
6126 return getSize($_[0]);
6127 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006128 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006129 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006130}
6131
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006132sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006133{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006134 if(my $Chan = getTreeAttr_Chan($_[0])) {
6135 return $Chan;
6136 }
6137 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6138 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006139 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006140 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006141}
6142
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006143sub registerHeader($$)
6144{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006145 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006146 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006147 return "";
6148 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006149 if(is_abs($Header) and not -f $Header)
6150 { # incorrect absolute path
6151 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006152 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006153 if(skipHeader($Header, $LibVersion))
6154 { # skip
6155 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006156 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006157 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6158 {
6159 detect_header_includes($Header_Path, $LibVersion);
6160
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006161 if(defined $Tolerance and $Tolerance=~/3/)
6162 { # 3 - skip headers that include non-Linux headers
6163 if($OSgroup ne "windows")
6164 {
6165 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6166 {
6167 if(specificHeader($Inc, "windows")) {
6168 return "";
6169 }
6170 }
6171 }
6172 }
6173
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006174 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6175 { # redirect
6176 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6177 or skipHeader($RHeader_Path, $LibVersion))
6178 { # skip
6179 return "";
6180 }
6181 $Header_Path = $RHeader_Path;
6182 }
6183 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6184 { # skip
6185 return "";
6186 }
6187
6188 if(my $HName = get_filename($Header_Path))
6189 { # register
6190 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6191 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6192 }
6193
6194 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6195 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006196 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006197 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006198 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006199 }
6200
6201 if($CheckHeadersOnly
6202 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6203 { # /usr/include/c++/4.6.1/...
6204 $STDCXX_TESTING = 1;
6205 }
6206
6207 return $Header_Path;
6208 }
6209 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006210}
6211
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006212sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006213{
6214 my ($Dir, $WithDeps, $LibVersion) = @_;
6215 $Dir=~s/[\/\\]+\Z//g;
6216 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006217 $Dir = get_abs_path($Dir);
6218 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006219 if($WithDeps)
6220 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006221 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6222 return;
6223 }
6224 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6225 $Mode = "DepsOnly";
6226 }
6227 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006228 else
6229 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006230 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6231 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6232 return;
6233 }
6234 }
6235 $Header_Dependency{$LibVersion}{$Dir} = 1;
6236 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6237 if($Mode eq "DepsOnly")
6238 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006239 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006240 $Header_Dependency{$LibVersion}{$Path} = 1;
6241 }
6242 return;
6243 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006244 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006245 {
6246 if($WithDeps)
6247 {
6248 my $SubDir = $Path;
6249 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6250 { # register all sub directories
6251 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6252 }
6253 }
6254 next if(is_not_header($Path));
6255 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006256 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006257 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006258 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6259 }
6260 }
6261 if(get_filename($Dir) eq "include")
6262 { # search for "lib/include/" directory
6263 my $LibDir = $Dir;
6264 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006265 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006266 }
6267 }
6268}
6269
6270sub parse_redirect($$$)
6271{
6272 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006273 my @Errors = ();
6274 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6275 push(@Errors, $1);
6276 }
6277 my $Redirect = "";
6278 foreach (@Errors)
6279 {
6280 s/\s{2,}/ /g;
6281 if(/(only|must\ include
6282 |update\ to\ include
6283 |replaced\ with
6284 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006285 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006286 {
6287 $Redirect = $2;
6288 last;
6289 }
6290 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6291 {
6292 $Redirect = $2;
6293 last;
6294 }
6295 elsif(/this\ header\ should\ not\ be\ used
6296 |programs\ should\ not\ directly\ include
6297 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6298 |is\ not\ supported\ API\ for\ general\ use
6299 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006300 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006301 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6302 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6303 }
6304 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006305 if($Redirect)
6306 {
6307 $Redirect=~s/\A<//g;
6308 $Redirect=~s/>\Z//g;
6309 }
6310 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006311}
6312
6313sub parse_includes($$)
6314{
6315 my ($Content, $Path) = @_;
6316 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006317 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006318 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006319 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006320 my $Method = substr($Header, 0, 1, "");
6321 substr($Header, length($Header)-1, 1, "");
6322 $Header = path_format($Header, $OSgroup);
6323 if($Method eq "\"" or is_abs($Header))
6324 {
6325 if(-e join_P(get_dirname($Path), $Header))
6326 { # relative path exists
6327 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006328 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006329 else
6330 { # include "..." that doesn't exist is equal to include <...>
6331 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006332 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006333 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006334 else {
6335 $Includes{$Header} = 1;
6336 }
6337 }
6338 if($ExtraInfo)
6339 {
6340 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6341 { # FT_FREETYPE_H
6342 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006343 }
6344 }
6345 return \%Includes;
6346}
6347
6348sub ignore_path($)
6349{
6350 my $Path = $_[0];
6351 if($Path=~/\~\Z/)
6352 {# skipping system backup files
6353 return 1;
6354 }
6355 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6356 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6357 return 1;
6358 }
6359 return 0;
6360}
6361
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006362sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006363{
6364 my ($ArrRef, $W) = @_;
6365 return if(length($W)<2);
6366 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6367}
6368
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006369sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006370{
6371 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006372
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006373 $H1=~s/\.[a-z]+\Z//ig;
6374 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006375
6376 my $Hname1 = get_filename($H1);
6377 my $Hname2 = get_filename($H2);
6378 my $HDir1 = get_dirname($H1);
6379 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006380 my $Dirname1 = get_filename($HDir1);
6381 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006382
6383 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6384 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6385
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006386 if($_[0] eq $_[1]
6387 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006388 return 0;
6389 }
6390 elsif($H1=~/\A\Q$H2\E/) {
6391 return 1;
6392 }
6393 elsif($H2=~/\A\Q$H1\E/) {
6394 return -1;
6395 }
6396 elsif($HDir1=~/\Q$Hname1\E/i
6397 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006398 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006399 return -1;
6400 }
6401 elsif($HDir2=~/\Q$Hname2\E/i
6402 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006403 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006404 return 1;
6405 }
6406 elsif($Hname1=~/\Q$Dirname1\E/i
6407 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006408 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006409 return -1;
6410 }
6411 elsif($Hname2=~/\Q$Dirname2\E/i
6412 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006413 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006414 return 1;
6415 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006416 elsif($Hname1=~/(config|lib|util)/i
6417 and $Hname2!~/(config|lib|util)/i)
6418 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006419 return -1;
6420 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006421 elsif($Hname2=~/(config|lib|util)/i
6422 and $Hname1!~/(config|lib|util)/i)
6423 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006424 return 1;
6425 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006426 else
6427 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006428 my $R1 = checkRelevance($H1);
6429 my $R2 = checkRelevance($H2);
6430 if($R1 and not $R2)
6431 { # libebook/e-book.h
6432 return -1;
6433 }
6434 elsif($R2 and not $R1)
6435 { # libebook/e-book.h
6436 return 1;
6437 }
6438 else
6439 {
6440 return (lc($H1) cmp lc($H2));
6441 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006442 }
6443}
6444
6445sub searchForHeaders($)
6446{
6447 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006448
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006449 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006450 registerGccHeaders();
6451
6452 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6453 { # c++ standard include paths
6454 registerCppHeaders();
6455 }
6456
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006457 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006458 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6459 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006460 {
6461 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006462 if($SystemRoot)
6463 {
6464 if(is_abs($Path)) {
6465 $Path = $SystemRoot.$Path;
6466 }
6467 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006468 if(not -e $Path) {
6469 exitStatus("Access_Error", "can't access \'$Path\'");
6470 }
6471 elsif(-f $Path) {
6472 exitStatus("Access_Error", "\'$Path\' - not a directory");
6473 }
6474 elsif(-d $Path)
6475 {
6476 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006477 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006478 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6479 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006480 }
6481 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006482 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006483 }
6484 }
6485 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006486 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006487 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6488 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006489
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006490 # registering directories
6491 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6492 {
6493 next if(not -e $Path);
6494 $Path = get_abs_path($Path);
6495 $Path = path_format($Path, $OSgroup);
6496 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006497 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006498 }
6499 elsif(-f $Path)
6500 {
6501 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006502 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006503 and not $LocalIncludes{$Dir})
6504 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006505 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006506 # if(my $OutDir = get_dirname($Dir))
6507 # { # registering the outer directory
6508 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6509 # and not $LocalIncludes{$OutDir}) {
6510 # registerDir($OutDir, 0, $LibVersion);
6511 # }
6512 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006513 }
6514 }
6515 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006516
6517 # clean memory
6518 %RegisteredDirs = ();
6519
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006520 # registering headers
6521 my $Position = 0;
6522 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6523 {
6524 if(is_abs($Dest) and not -e $Dest) {
6525 exitStatus("Access_Error", "can't access \'$Dest\'");
6526 }
6527 $Dest = path_format($Dest, $OSgroup);
6528 if(is_header($Dest, 1, $LibVersion))
6529 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006530 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006531 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6532 }
6533 }
6534 elsif(-d $Dest)
6535 {
6536 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006537 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006538 {
6539 next if(ignore_path($Path));
6540 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006541 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006542 push(@Registered, $HPath);
6543 }
6544 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006545 @Registered = sort {sortHeaders($a, $b)} @Registered;
6546 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006547 foreach my $Path (@Registered) {
6548 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6549 }
6550 }
6551 else {
6552 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6553 }
6554 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006555
6556 if(defined $Tolerance and $Tolerance=~/4/)
6557 { # 4 - skip headers included by others
6558 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6559 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006560 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006561 delete($Registered_Headers{$LibVersion}{$Path});
6562 }
6563 }
6564 }
6565
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006566 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6567 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006568 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006569 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006570 if(is_abs($Header) and not -f $Header) {
6571 exitStatus("Access_Error", "can't access file \'$Header\'");
6572 }
6573 $Header = path_format($Header, $OSgroup);
6574 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6575 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006576 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006577 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006578 }
6579 else {
6580 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6581 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006582 }
6583 }
6584 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6585 { # set relative paths (for duplicates)
6586 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6587 { # search for duplicates
6588 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6589 my $Prefix = get_dirname($FirstPath);
6590 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6591 { # detect a shortest distinguishing prefix
6592 my $NewPrefix = $1;
6593 my %Identity = ();
6594 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6595 {
6596 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6597 $Identity{$Path} = $1;
6598 }
6599 }
6600 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6601 { # all names are differend with current prefix
6602 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6603 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6604 }
6605 last;
6606 }
6607 $Prefix = $NewPrefix; # increase prefix
6608 }
6609 }
6610 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006611
6612 # clean memory
6613 %HeaderName_Paths = ();
6614
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006615 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6616 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006617 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006618 my ($Pos, $PairPos) = (-1, -1);
6619 my ($Path, $PairPath) = ();
6620 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6621 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6622 foreach my $Header_Path (@Paths)
6623 {
6624 if(get_filename($Header_Path) eq $PairName)
6625 {
6626 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6627 $PairPath = $Header_Path;
6628 }
6629 if(get_filename($Header_Path) eq $HeaderName)
6630 {
6631 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6632 $Path = $Header_Path;
6633 }
6634 }
6635 if($PairPos!=-1 and $Pos!=-1
6636 and int($PairPos)<int($Pos))
6637 {
6638 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6639 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6640 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6641 }
6642 }
6643 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6644 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6645 }
6646}
6647
6648sub detect_real_includes($$)
6649{
6650 my ($AbsPath, $LibVersion) = @_;
6651 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6652 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6653 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6654 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6655 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006656 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6657
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006658 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6659 return () if(not $Path);
6660 open(PREPROC, $Path);
6661 while(<PREPROC>)
6662 {
6663 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6664 {
6665 my $Include = path_format($1, $OSgroup);
6666 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6667 next;
6668 }
6669 if($Include eq $AbsPath) {
6670 next;
6671 }
6672 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6673 }
6674 }
6675 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006676 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6677}
6678
6679sub detect_header_includes($$)
6680{
6681 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006682 return if(not $LibVersion or not $Path);
6683 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6684 return;
6685 }
6686 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6687
6688 if(not -e $Path) {
6689 return;
6690 }
6691
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006692 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006693 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6694 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006695 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006696 {
6697 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006698 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006699 }
6700 if($RedirectPath ne $Path) {
6701 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6702 }
6703 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006704 else
6705 { # can't find
6706 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006708 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006709 if(my $Inc = parse_includes($Content, $Path))
6710 {
6711 foreach my $Include (keys(%{$Inc}))
6712 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006713 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006714
6715 if(defined $Tolerance and $Tolerance=~/4/)
6716 {
6717 if(my $HPath = identifyHeader($Include, $LibVersion))
6718 {
6719 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6720 }
6721 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006722 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006723 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006724}
6725
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006726sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006727{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006728 my $Path = $_[0];
6729 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006730 if($OStarget eq "symbian")
6731 {
6732 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6733 { # epoc32/include/libc/{stdio, ...}.h
6734 return 1;
6735 }
6736 }
6737 else
6738 {
6739 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6740 { # /usr/include/{stdio, ...}.h
6741 return 1;
6742 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006743 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006744 return 0;
6745}
6746
6747sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006748{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006749 my $Dir = $_[0];
6750 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006751 if($OStarget eq "symbian")
6752 {
6753 if(get_filename($OutDir) eq "libc"
6754 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6755 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6756 return 1;
6757 }
6758 }
6759 else
6760 { # linux
6761 if($OutDir eq "/usr/include"
6762 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6763 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6764 return 1;
6765 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006766 }
6767 return 0;
6768}
6769
6770sub detect_recursive_includes($$)
6771{
6772 my ($AbsPath, $LibVersion) = @_;
6773 return () if(not $AbsPath);
6774 if(isCyclical(\@RecurInclude, $AbsPath)) {
6775 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6776 }
6777 my ($AbsDir, $Name) = separate_path($AbsPath);
6778 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006779 { # system GLIBC internals
6780 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006781 }
6782 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6783 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6784 }
6785 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006786
6787 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6788 { # skip /usr/include/c++/*/ headers
6789 return () if(not $ExtraInfo);
6790 }
6791
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006792 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006793 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006794 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006795 { # check "real" (non-"model") include paths
6796 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6797 pop(@RecurInclude);
6798 return @Paths;
6799 }
6800 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6801 detect_header_includes($AbsPath, $LibVersion);
6802 }
6803 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6804 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006805 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006806 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006807 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006808 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006809 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006810 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006811 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006812 }
6813 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006814 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006815 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006816 { # search for the nearest header
6817 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006818 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006819 if(-f $Candidate) {
6820 $HPath = $Candidate;
6821 }
6822 }
6823 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006824 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006825 }
6826 next if(not $HPath);
6827 if($HPath eq $AbsPath) {
6828 next;
6829 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006830
6831 if($Debug)
6832 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006833# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6834# {
6835# print STDERR "$AbsPath -> $HPath\n";
6836# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006837 }
6838
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006839 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6840 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006841 { # only include <...>, skip include "..." prefixes
6842 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6843 }
6844 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6845 {
6846 if($IncPath eq $AbsPath) {
6847 next;
6848 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006849 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6850 if($RIncType==-1)
6851 { # include "..."
6852 $RIncType = $IncType;
6853 }
6854 elsif($RIncType==2)
6855 {
6856 if($IncType!=-1) {
6857 $RIncType = $IncType;
6858 }
6859 }
6860 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006861 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6862 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6863 }
6864 }
6865 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6866 {
6867 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6868 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6869 { # distinguish math.h from glibc and math.h from the tested library
6870 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6871 last;
6872 }
6873 }
6874 }
6875 pop(@RecurInclude);
6876 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6877}
6878
6879sub find_in_framework($$$)
6880{
6881 my ($Header, $Framework, $LibVersion) = @_;
6882 return "" if(not $Header or not $Framework or not $LibVersion);
6883 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6884 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6885 }
6886 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6887 {
6888 if(get_filename($Dependency) eq $Framework
6889 and -f get_dirname($Dependency)."/".$Header) {
6890 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6891 }
6892 }
6893 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6894}
6895
6896sub find_in_defaults($)
6897{
6898 my $Header = $_[0];
6899 return "" if(not $Header);
6900 if(defined $Cache{"find_in_defaults"}{$Header}) {
6901 return $Cache{"find_in_defaults"}{$Header};
6902 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006903 foreach my $Dir (@DefaultIncPaths,
6904 @DefaultGccPaths,
6905 @DefaultCppPaths,
6906 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006907 {
6908 next if(not $Dir);
6909 if(-f $Dir."/".$Header) {
6910 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6911 }
6912 }
6913 return ($Cache{"find_in_defaults"}{$Header}="");
6914}
6915
6916sub cmp_paths($$)
6917{
6918 my ($Path1, $Path2) = @_;
6919 my @Parts1 = split(/[\/\\]/, $Path1);
6920 my @Parts2 = split(/[\/\\]/, $Path2);
6921 foreach my $Num (0 .. $#Parts1)
6922 {
6923 my $Part1 = $Parts1[$Num];
6924 my $Part2 = $Parts2[$Num];
6925 if($GlibcDir{$Part1}
6926 and not $GlibcDir{$Part2}) {
6927 return 1;
6928 }
6929 elsif($GlibcDir{$Part2}
6930 and not $GlibcDir{$Part1}) {
6931 return -1;
6932 }
6933 elsif($Part1=~/glib/
6934 and $Part2!~/glib/) {
6935 return 1;
6936 }
6937 elsif($Part1!~/glib/
6938 and $Part2=~/glib/) {
6939 return -1;
6940 }
6941 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6942 return $CmpRes;
6943 }
6944 }
6945 return 0;
6946}
6947
6948sub checkRelevance($)
6949{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006950 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006951 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006952
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006953 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006954 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006955 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006956
6957 my $Name = lc(get_filename($Path));
6958 my $Dir = lc(get_dirname($Path));
6959
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006960 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006961
6962 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006963 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006964 my $Len = length($Token);
6965 next if($Len<=1);
6966 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6967 { # include/evolution-data-server-1.4/libebook/e-book.h
6968 return 1;
6969 }
6970 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006971 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006972 return 1;
6973 }
6974 }
6975 return 0;
6976}
6977
6978sub checkFamily(@)
6979{
6980 my @Paths = @_;
6981 return 1 if($#Paths<=0);
6982 my %Prefix = ();
6983 foreach my $Path (@Paths)
6984 {
6985 if($SystemRoot) {
6986 $Path = cut_path_prefix($Path, $SystemRoot);
6987 }
6988 if(my $Dir = get_dirname($Path))
6989 {
6990 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6991 $Prefix{$Dir} += 1;
6992 $Prefix{get_dirname($Dir)} += 1;
6993 }
6994 }
6995 foreach (sort keys(%Prefix))
6996 {
6997 if(get_depth($_)>=3
6998 and $Prefix{$_}==$#Paths+1) {
6999 return 1;
7000 }
7001 }
7002 return 0;
7003}
7004
7005sub isAcceptable($$$)
7006{
7007 my ($Header, $Candidate, $LibVersion) = @_;
7008 my $HName = get_filename($Header);
7009 if(get_dirname($Header))
7010 { # with prefix
7011 return 1;
7012 }
7013 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
7014 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
7015 return 1;
7016 }
7017 if(checkRelevance($Candidate))
7018 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
7019 return 1;
7020 }
7021 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
7022 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
7023 # /usr/include/qt4/Qt/qsslconfiguration.h
7024 return 1;
7025 }
7026 if($OStarget eq "symbian")
7027 {
7028 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
7029 return 1;
7030 }
7031 }
7032 return 0;
7033}
7034
7035sub isRelevant($$$)
7036{ # disallow to search for "abstract" headers in too deep directories
7037 my ($Header, $Candidate, $LibVersion) = @_;
7038 my $HName = get_filename($Header);
7039 if($OStarget eq "symbian")
7040 {
7041 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7042 return 0;
7043 }
7044 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007045 if($OStarget ne "bsd")
7046 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007047 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7048 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7049 return 0;
7050 }
7051 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007052 if($OStarget ne "windows")
7053 {
7054 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7055 { # skip /usr/include/wine/msvcrt
7056 return 0;
7057 }
7058 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007059 if(not get_dirname($Header)
7060 and $Candidate=~/[\/\\]wx[\/\\]/)
7061 { # do NOT search in system /wx/ directory
7062 # for headers without a prefix: sstream.h
7063 return 0;
7064 }
7065 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7066 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7067 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7068 return 0;
7069 }
7070 if($Candidate=~/[\/\\]asm-/
7071 and (my $Arch = getArch($LibVersion)) ne "unknown")
7072 { # arch-specific header files
7073 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7074 {# skip ../asm-arm/ if using x86 architecture
7075 return 0;
7076 }
7077 }
7078 my @Candidates = getSystemHeaders($HName, $LibVersion);
7079 if($#Candidates==1)
7080 { # unique header
7081 return 1;
7082 }
7083 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7084 if($#SCandidates==1)
7085 { # unique name
7086 return 1;
7087 }
7088 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7089 if(get_depth($Candidate)-$SystemDepth>=5)
7090 { # abstract headers in too deep directories
7091 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7092 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7093 return 0;
7094 }
7095 }
7096 if($Header eq "parser.h"
7097 and $Candidate!~/\/libxml2\//)
7098 { # select parser.h from xml2 library
7099 return 0;
7100 }
7101 if(not get_dirname($Header)
7102 and keys(%{$SystemHeaders{$HName}})>=3)
7103 { # many headers with the same name
7104 # like thread.h included without a prefix
7105 if(not checkFamily(@Candidates)) {
7106 return 0;
7107 }
7108 }
7109 return 1;
7110}
7111
7112sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007113{ # cache function
7114 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7115 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7116 }
7117 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7118}
7119
7120sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007121{
7122 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007123 if(-f $Header) {
7124 return $Header;
7125 }
7126 if(is_abs($Header) and not -f $Header)
7127 { # incorrect absolute path
7128 return "";
7129 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007130 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007131 { # too abstract configuration headers
7132 return "";
7133 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007134 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007135 if($OSgroup ne "windows")
7136 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007137 if(defined $WinHeaders{lc($HName)}
7138 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007139 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007140 return "";
7141 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007142 }
7143 if($OSgroup ne "macos")
7144 {
7145 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007146 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007147 return "";
7148 }
7149 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007150
7151 if(defined $ObsoleteHeaders{$HName})
7152 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007153 return "";
7154 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007155 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7156 {
7157 if(defined $AlienHeaders{$HName}
7158 or defined $AlienHeaders{$Header})
7159 { # alien headers from other systems
7160 return "";
7161 }
7162 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007163
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007164 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007165 { # search in default paths
7166 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007167 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007168 }
7169 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007170 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007171 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007172 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007173 }
7174 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7175 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7176 {
7177 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007178 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007179 }
7180 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007181 # error
7182 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007183}
7184
7185sub getSystemHeaders($$)
7186{
7187 my ($Header, $LibVersion) = @_;
7188 my @Candidates = ();
7189 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7190 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007191 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007192 next;
7193 }
7194 push(@Candidates, $Candidate);
7195 }
7196 return @Candidates;
7197}
7198
7199sub cut_path_prefix($$)
7200{
7201 my ($Path, $Prefix) = @_;
7202 return $Path if(not $Prefix);
7203 $Prefix=~s/[\/\\]+\Z//;
7204 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7205 return $Path;
7206}
7207
7208sub is_default_include_dir($)
7209{
7210 my $Dir = $_[0];
7211 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007212 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007213}
7214
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007215sub identifyHeader($$)
7216{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007217 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007218 if(not $Header) {
7219 return "";
7220 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007221 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007222 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7223 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007224 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007225 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007226}
7227
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007228sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007229{ # search for header by absolute path, relative path or name
7230 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007231 if(-f $Header)
7232 { # it's relative or absolute path
7233 return get_abs_path($Header);
7234 }
7235 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7236 and my $HeaderDir = find_in_defaults($Header))
7237 { # search for libc headers in the /usr/include
7238 # for non-libc target library before searching
7239 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007240 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007241 }
7242 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7243 { # search in the target library paths
7244 return $Path;
7245 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007246 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007247 { # search in the internal GCC include paths
7248 return $DefaultGccHeader{$Header};
7249 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007250 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007251 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007252 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007253 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007254 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007255 { # search in the default G++ include paths
7256 return $DefaultCppHeader{$Header};
7257 }
7258 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7259 { # search everywhere in the system
7260 return $AnyPath;
7261 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007262 elsif($OSgroup eq "macos")
7263 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7264 if(my $Dir = get_dirname($Header))
7265 {
7266 my $RelPath = "Headers\/".get_filename($Header);
7267 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007268 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007269 }
7270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007271 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007272 # cannot find anything
7273 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007274}
7275
7276sub getLocation($)
7277{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007278 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7279 {
7280 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007281 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007282 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007283 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007284 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007285}
7286
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007287sub getNameByInfo($)
7288{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007289 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007290 {
7291 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7292 {
7293 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7294 {
7295 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7296 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007297 my $Str = $1;
7298 if($CppMode{$Version}
7299 and $Str=~/\Ac99_(.+)\Z/)
7300 {
7301 if($CppKeywords_A{$1}) {
7302 $Str=$1;
7303 }
7304 }
7305 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007306 }
7307 }
7308 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007309 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007310 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007311}
7312
7313sub getTreeStr($)
7314{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007315 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007316 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007317 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7318 {
7319 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007320 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007321 and $Str=~/\Ac99_(.+)\Z/)
7322 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007323 if($CppKeywords_A{$1}) {
7324 $Str=$1;
7325 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007326 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007327 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007328 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007329 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007330 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007331}
7332
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007333sub getFuncShortName($)
7334{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007335 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007336 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007337 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007338 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007339 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007340 {
7341 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7342 {
7343 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7344 return "operator ".$RName;
7345 }
7346 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007347 }
7348 else
7349 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007350 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7351 {
7352 if(my $Ind = $Operator_Indication{$1}) {
7353 return "operator".$Ind;
7354 }
7355 elsif(not $UnknownOperator{$1})
7356 {
7357 printMsg("WARNING", "unknown operator $1");
7358 $UnknownOperator{$1} = 1;
7359 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007360 }
7361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007362 }
7363 else
7364 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007365 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7366 return getTreeStr($1);
7367 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007368 }
7369 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007370 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007371}
7372
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007373sub getFuncReturn($)
7374{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007375 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7376 {
7377 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7378 {
7379 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7380 return $1;
7381 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007382 }
7383 }
7384 return "";
7385}
7386
7387sub getFuncOrig($)
7388{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007389 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7390 {
7391 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7392 return $1;
7393 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007394 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007395 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007396}
7397
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007398sub unmangleArray(@)
7399{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007400 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007401 { # MSVC mangling
7402 my $UndNameCmd = get_CmdPath("undname");
7403 if(not $UndNameCmd) {
7404 exitStatus("Not_Found", "can't find \"undname\"");
7405 }
7406 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007407 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007408 }
7409 else
7410 { # GCC mangling
7411 my $CppFiltCmd = get_CmdPath("c++filt");
7412 if(not $CppFiltCmd) {
7413 exitStatus("Not_Found", "can't find c++filt in PATH");
7414 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007415 if(not defined $CPPFILT_SUPPORT_FILE)
7416 {
7417 my $Info = `$CppFiltCmd -h 2>&1`;
7418 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7419 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007420 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007421 if($CPPFILT_SUPPORT_FILE)
7422 { # new versions of c++filt can take a file
7423 if($#_>$MAX_CPPFILT_FILE_SIZE)
7424 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7425 # this is fixed in the oncoming version of Binutils
7426 my @Half = splice(@_, 0, ($#_+1)/2);
7427 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007428 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007429 else
7430 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007431 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7432 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7433 if($?==139)
7434 { # segmentation fault
7435 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7436 }
7437 return split(/\n/, $Res);
7438 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007439 }
7440 else
7441 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007442 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7443 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007444 my @Half = splice(@_, 0, ($#_+1)/2);
7445 return (unmangleArray(@Half), unmangleArray(@_))
7446 }
7447 else
7448 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007449 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007450 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7451 if($?==139)
7452 { # segmentation fault
7453 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7454 }
7455 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007456 }
7457 }
7458 }
7459}
7460
7461sub get_SignatureNoInfo($$)
7462{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007463 my ($Symbol, $LibVersion) = @_;
7464 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
7465 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007466 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007467 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007468 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007469 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007470 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04007471 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007472 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
7473 $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;
7474 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007475 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007476 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007477 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007478 $Signature .= " [data]";
7479 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007480 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007481 $Signature .= " (...)";
7482 }
7483 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007484 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007485 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04007486 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007487 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
7488 }
7489 if($SymbolVersion) {
7490 $Signature .= $VersionSpec.$SymbolVersion;
7491 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007492 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007493}
7494
7495sub get_ChargeLevel($$)
7496{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007497 my ($Symbol, $LibVersion) = @_;
7498 return "" if($Symbol!~/\A(_Z|\?)/);
7499 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7500 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007501 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007502 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007503 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007504 if($Symbol=~/C1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007505 return "[in-charge]";
7506 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007507 elsif($Symbol=~/C2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007508 return "[not-in-charge]";
7509 }
7510 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007511 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007512 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007513 if($Symbol=~/D1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007514 return "[in-charge]";
7515 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007516 elsif($Symbol=~/D2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007517 return "[not-in-charge]";
7518 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007519 elsif($Symbol=~/D0E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007520 return "[in-charge-deleting]";
7521 }
7522 }
7523 }
7524 else
7525 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007526 if($Symbol=~/C1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007527 return "[in-charge]";
7528 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007529 elsif($Symbol=~/C2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007530 return "[not-in-charge]";
7531 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007532 elsif($Symbol=~/D1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007533 return "[in-charge]";
7534 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007535 elsif($Symbol=~/D2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007536 return "[not-in-charge]";
7537 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007538 elsif($Symbol=~/D0E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007539 return "[in-charge-deleting]";
7540 }
7541 }
7542 return "";
7543}
7544
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007545sub get_Signature_M($$)
7546{
7547 my ($Symbol, $LibVersion) = @_;
7548 my $Signature_M = $tr_name{$Symbol};
7549 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7550 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007551 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007552 }
7553 return $Signature_M;
7554}
7555
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007556sub get_Signature($$)
7557{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007558 my ($Symbol, $LibVersion) = @_;
7559 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7560 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007561 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007562 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
7563 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007564 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007565 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007566 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007567 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007568 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7569 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007570 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007571 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7572 {
7573 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7574 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7575 $Signature .= "~";
7576 }
7577 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007578 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007579 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007580 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007581 }
7582 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007583 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007584 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007585 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7586 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007587 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007588 else
7589 {
7590 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007591 }
7592 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007593 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007594 {
7595 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007596 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007597 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007598 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007599 if(not $ParamTypeName) {
7600 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7601 }
7602 foreach my $Typedef (keys(%ChangedTypedef))
7603 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007604 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7605 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7606 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007607 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007608 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7609 {
7610 if($ParamName ne "this" or $Symbol!~/\A(_Z|\?)/)
7611 { # do NOT show first hidded "this"-parameter
7612 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
7613 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007614 }
7615 else {
7616 push(@ParamArray, $ParamTypeName);
7617 }
7618 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007619 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7620 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007621 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007622 }
7623 else
7624 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007625 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007626 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007627 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007628 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007629 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007630 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7631 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007632 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007633 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007634 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7635 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007636 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007637 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007638 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7639 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007640 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007641 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007642 }
7643 }
7644 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007645 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007646 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007647 }
7648 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007649 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007650 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007651 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007652}
7653
7654sub create_member_decl($$)
7655{
7656 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007657 if($TName=~/\([\*]+\)/)
7658 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007659 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7660 return $TName;
7661 }
7662 else
7663 {
7664 my @ArraySizes = ();
7665 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7666 push(@ArraySizes, $1);
7667 }
7668 return $TName." ".$Member.join("", @ArraySizes);
7669 }
7670}
7671
7672sub getFuncType($)
7673{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007674 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7675 {
7676 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7677 {
7678 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7679 {
7680 if($Type eq "method_type") {
7681 return "Method";
7682 }
7683 elsif($Type eq "function_type") {
7684 return "Function";
7685 }
7686 else {
7687 return "Other";
7688 }
7689 }
7690 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007691 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007692 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007693}
7694
7695sub getFuncTypeId($)
7696{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007697 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7698 {
7699 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7700 return $1;
7701 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007702 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007703 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007704}
7705
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007706sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007707{ # "._N" or "$_N" in older GCC versions
7708 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007709}
7710
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007711sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007712{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007713 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7714 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007715 }
7716
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007717 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007718
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007719 if($_[1] ne "S")
7720 {
7721 $N=~s/\A[ ]+//g;
7722 $N=~s/[ ]+\Z//g;
7723 $N=~s/[ ]{2,}/ /g;
7724 }
7725
7726 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007727
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007728 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007729
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007730 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7731 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007732
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007733 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007734
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007735 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007736
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007737 if($_[1] eq "S")
7738 {
7739 if(index($N, "operator")!=-1) {
7740 $N=~s/\b(operator[ ]*)> >/$1>>/;
7741 }
7742 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007743
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007744 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007745}
7746
7747sub get_HeaderDeps($$)
7748{
7749 my ($AbsPath, $LibVersion) = @_;
7750 return () if(not $AbsPath or not $LibVersion);
7751 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7752 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7753 }
7754 my %IncDir = ();
7755 detect_recursive_includes($AbsPath, $LibVersion);
7756 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7757 {
7758 next if(not $HeaderPath);
7759 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7760 my $Dir = get_dirname($HeaderPath);
7761 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7762 {
7763 my $Dep = $Dir;
7764 if($Prefix)
7765 {
7766 if($OSgroup eq "windows")
7767 { # case insensitive seach on windows
7768 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7769 next;
7770 }
7771 }
7772 elsif($OSgroup eq "macos")
7773 { # seach in frameworks
7774 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7775 {
7776 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7777 {# frameworks
7778 my ($HFramework, $HName) = ($1, $2);
7779 $Dep = $HFramework;
7780 }
7781 else
7782 {# mismatch
7783 next;
7784 }
7785 }
7786 }
7787 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7788 { # Linux, FreeBSD
7789 next;
7790 }
7791 }
7792 if(not $Dep)
7793 { # nothing to include
7794 next;
7795 }
7796 if(is_default_include_dir($Dep))
7797 { # included by the compiler
7798 next;
7799 }
7800 if(get_depth($Dep)==1)
7801 { # too short
7802 next;
7803 }
7804 if(isLibcDir($Dep))
7805 { # do NOT include /usr/include/{sys,bits}
7806 next;
7807 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007808 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007809 }
7810 }
7811 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7812 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7813}
7814
7815sub sortIncPaths($$)
7816{
7817 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007818 if(not $ArrRef or $#{$ArrRef}<0) {
7819 return $ArrRef;
7820 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007821 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7822 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007823 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007824 return $ArrRef;
7825}
7826
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007827sub sortDeps($$$)
7828{
7829 if($Header_Dependency{$_[2]}{$_[0]}
7830 and not $Header_Dependency{$_[2]}{$_[1]}) {
7831 return 1;
7832 }
7833 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7834 and $Header_Dependency{$_[2]}{$_[1]}) {
7835 return -1;
7836 }
7837 return 0;
7838}
7839
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007840sub join_P($$)
7841{
7842 my $S = "/";
7843 if($OSgroup eq "windows") {
7844 $S = "\\";
7845 }
7846 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007847}
7848
7849sub get_namespace_additions($)
7850{
7851 my $NameSpaces = $_[0];
7852 my ($Additions, $AddNameSpaceId) = ("", 1);
7853 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7854 {
7855 next if($SkipNameSpaces{$Version}{$NS});
7856 next if(not $NS or $NameSpaces->{$NS}==-1);
7857 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7858 next if($NS=~/\A__/i);
7859 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007860 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007861 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7862 my @NS_Parts = split(/::/, $NS);
7863 next if($#NS_Parts==-1);
7864 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7865 foreach my $NS_Part (@NS_Parts)
7866 {
7867 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7868 $TypeDecl_Suffix .= "}";
7869 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007870 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007871 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7872 $Additions.=" $TypeDecl\n $FuncDecl\n";
7873 $AddNameSpaceId+=1;
7874 }
7875 return $Additions;
7876}
7877
7878sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007879{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007880 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007881 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007882 if($Fmt eq "windows")
7883 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007884 $Path=~s/\//\\/g;
7885 $Path=lc($Path);
7886 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007887 else
7888 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007889 $Path=~s/\\/\//g;
7890 }
7891 return $Path;
7892}
7893
7894sub inc_opt($$)
7895{
7896 my ($Path, $Style) = @_;
7897 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007898 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007899 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007900 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007901 return "-I\"".path_format($Path, "unix")."\"";
7902 }
7903 elsif($OSgroup eq "macos"
7904 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007905 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007906 return "-F".esc(get_dirname($Path));
7907 }
7908 else {
7909 return "-I".esc($Path);
7910 }
7911 }
7912 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007913 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007914 }
7915 return "";
7916}
7917
7918sub platformSpecs($)
7919{
7920 my $LibVersion = $_[0];
7921 my $Arch = getArch($LibVersion);
7922 if($OStarget eq "symbian")
7923 { # options for GCCE compiler
7924 my %Symbian_Opts = map {$_=>1} (
7925 "-D__GCCE__",
7926 "-DUNICODE",
7927 "-fexceptions",
7928 "-D__SYMBIAN32__",
7929 "-D__MARM_INTERWORK__",
7930 "-D_UNICODE",
7931 "-D__S60_50__",
7932 "-D__S60_3X__",
7933 "-D__SERIES60_3X__",
7934 "-D__EPOC32__",
7935 "-D__MARM__",
7936 "-D__EABI__",
7937 "-D__MARM_ARMV5__",
7938 "-D__SUPPORT_CPP_EXCEPTIONS__",
7939 "-march=armv5t",
7940 "-mapcs",
7941 "-mthumb-interwork",
7942 "-DEKA2",
7943 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7944 );
7945 return join(" ", keys(%Symbian_Opts));
7946 }
7947 elsif($OSgroup eq "windows"
7948 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7949 { # add options to MinGW compiler
7950 # to simulate the MSVC compiler
7951 my %MinGW_Opts = map {$_=>1} (
7952 "-D_WIN32",
7953 "-D_STDCALL_SUPPORTED",
7954 "-D__int64=\"long long\"",
7955 "-D__int32=int",
7956 "-D__int16=short",
7957 "-D__int8=char",
7958 "-D__possibly_notnullterminated=\" \"",
7959 "-D__nullterminated=\" \"",
7960 "-D__nullnullterminated=\" \"",
7961 "-D__w64=\" \"",
7962 "-D__ptr32=\" \"",
7963 "-D__ptr64=\" \"",
7964 "-D__forceinline=inline",
7965 "-D__inline=inline",
7966 "-D__uuidof(x)=IID()",
7967 "-D__try=",
7968 "-D__except(x)=",
7969 "-D__declspec(x)=__attribute__((x))",
7970 "-D__pragma(x)=",
7971 "-D_inline=inline",
7972 "-D__forceinline=__inline",
7973 "-D__stdcall=__attribute__((__stdcall__))",
7974 "-D__cdecl=__attribute__((__cdecl__))",
7975 "-D__fastcall=__attribute__((__fastcall__))",
7976 "-D__thiscall=__attribute__((__thiscall__))",
7977 "-D_stdcall=__attribute__((__stdcall__))",
7978 "-D_cdecl=__attribute__((__cdecl__))",
7979 "-D_fastcall=__attribute__((__fastcall__))",
7980 "-D_thiscall=__attribute__((__thiscall__))",
7981 "-DSHSTDAPI_(x)=x",
7982 "-D_MSC_EXTENSIONS",
7983 "-DSECURITY_WIN32",
7984 "-D_MSC_VER=1500",
7985 "-D_USE_DECLSPECS_FOR_SAL",
7986 "-D__noop=\" \"",
7987 "-DDECLSPEC_DEPRECATED=\" \"",
7988 "-D__builtin_alignof(x)=__alignof__(x)",
7989 "-DSORTPP_PASS");
7990 if($Arch eq "x86") {
7991 $MinGW_Opts{"-D_M_IX86=300"}=1;
7992 }
7993 elsif($Arch eq "x86_64") {
7994 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7995 }
7996 elsif($Arch eq "ia64") {
7997 $MinGW_Opts{"-D_M_IA64=300"}=1;
7998 }
7999 return join(" ", keys(%MinGW_Opts));
8000 }
8001 return "";
8002}
8003
8004my %C_Structure = map {$_=>1} (
8005# FIXME: Can't separate union and struct data types before dumping,
8006# so it sometimes cause compilation errors for unknown reason
8007# when trying to declare TYPE* tmp_add_class_N
8008# This is a list of such structures + list of other C structures
8009 "sigval",
8010 "sigevent",
8011 "sigaction",
8012 "sigvec",
8013 "sigstack",
8014 "timeval",
8015 "timezone",
8016 "rusage",
8017 "rlimit",
8018 "wait",
8019 "flock",
8020 "stat",
8021 "_stat",
8022 "stat32",
8023 "_stat32",
8024 "stat64",
8025 "_stat64",
8026 "_stati64",
8027 "if_nameindex",
8028 "usb_device",
8029 "sigaltstack",
8030 "sysinfo",
8031 "timeLocale",
8032 "tcp_debug",
8033 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008034 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008035 "timespec",
8036 "random_data",
8037 "drand48_data",
8038 "_IO_marker",
8039 "_IO_FILE",
8040 "lconv",
8041 "sched_param",
8042 "tm",
8043 "itimerspec",
8044 "_pthread_cleanup_buffer",
8045 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008046 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008047 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008048 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008049 "sigcontext",
8050 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008051 # Mac
8052 "_timex",
8053 "_class_t",
8054 "_category_t",
8055 "_class_ro_t",
8056 "_protocol_t",
8057 "_message_ref_t",
8058 "_super_message_ref_t",
8059 "_ivar_t",
8060 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008061);
8062
8063sub getCompileCmd($$$)
8064{
8065 my ($Path, $Opt, $Inc) = @_;
8066 my $GccCall = $GCC_PATH;
8067 if($Opt) {
8068 $GccCall .= " ".$Opt;
8069 }
8070 $GccCall .= " -x ";
8071 if($OSgroup eq "macos") {
8072 $GccCall .= "objective-";
8073 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008074 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008075 { # compile as "C++" header
8076 # to obtain complete dump using GCC 4.0
8077 $GccCall .= "c++-header";
8078 }
8079 else
8080 { # compile as "C++" source
8081 # GCC 3.3 cannot compile headers
8082 $GccCall .= "c++";
8083 }
8084 if(my $Opts = platformSpecs($Version))
8085 {# platform-specific options
8086 $GccCall .= " ".$Opts;
8087 }
8088 # allow extra qualifications
8089 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008090 $GccCall .= " -fpermissive";
8091 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008092 if($NoStdInc)
8093 {
8094 $GccCall .= " -nostdinc";
8095 $GccCall .= " -nostdinc++";
8096 }
8097 if($CompilerOptions{$Version})
8098 { # user-defined options
8099 $GccCall .= " ".$CompilerOptions{$Version};
8100 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008101 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008102 if($Inc)
8103 { # include paths
8104 $GccCall .= " ".$Inc;
8105 }
8106 return $GccCall;
8107}
8108
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008109sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008110{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008111 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008112 my %HeaderElems = (
8113 # Types
8114 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008115 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008116 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8117 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008118 "time.h" => ["time_t"],
8119 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008120 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8121 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008122 "stdbool.h" => ["_Bool"],
8123 "rpc/xdr.h" => ["bool_t"],
8124 "in_systm.h" => ["n_long", "n_short"],
8125 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008126 "arpa/inet.h" => ["fw_src", "ip_src"],
8127 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008128 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008129 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008130 );
8131 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008132 foreach (keys(%HeaderElems))
8133 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008134 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008135 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008136 }
8137 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008138 my %Types = ();
8139 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8140 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008141 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008142 }
8143 if(keys(%Types))
8144 {
8145 my %AddHeaders = ();
8146 foreach my $Type (keys(%Types))
8147 {
8148 if(my $Header = $AutoPreamble{$Type})
8149 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008150 if(my $Path = identifyHeader($Header, $LibVersion))
8151 {
8152 if(skipHeader($Path, $LibVersion)) {
8153 next;
8154 }
8155 $Path = path_format($Path, $OSgroup);
8156 $AddHeaders{$Path}{"Type"} = $Type;
8157 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008158 }
8159 }
8160 }
8161 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008162 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008163 }
8164 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008165 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008166}
8167
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008168sub checkCTags($)
8169{
8170 my $Path = $_[0];
8171 if(not $Path) {
8172 return;
8173 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008174 my $CTags = undef;
8175
8176 if($OSgroup eq "bsd")
8177 { # use ectags on BSD
8178 $CTags = get_CmdPath("ectags");
8179 if(not $CTags) {
8180 printMsg("WARNING", "can't find \'ectags\' program");
8181 }
8182 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008183 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008184 $CTags = get_CmdPath("ctags");
8185 }
8186 if(not $CTags)
8187 {
8188 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008189 return;
8190 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008191
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008192 if($OSgroup ne "linux")
8193 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008194 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8195 if($Info!~/exuberant/i)
8196 {
8197 printMsg("WARNING", "incompatible version of \'ctags\' program");
8198 return;
8199 }
8200 }
8201
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008202 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008203 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008204 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008205 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008206 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008207 open(CTAGS, "<", $Out);
8208 while(my $Line = <CTAGS>)
8209 {
8210 chomp($Line);
8211 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008212 if(defined $Intrinsic_Keywords{$Name})
8213 { # noise
8214 next;
8215 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008216 if($Type eq "n")
8217 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008218 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008219 next;
8220 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008221 if(index($Scpe, "struct:")==0) {
8222 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008223 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008224 if(index($Scpe, "namespace:")==0)
8225 {
8226 if($Scpe=~s/\Anamespace://) {
8227 $Name = $Scpe."::".$Name;
8228 }
8229 }
8230 $TUnit_NameSpaces{$Version}{$Name} = 1;
8231 }
8232 elsif($Type eq "p")
8233 {
8234 if(not $Scpe or index($Scpe, "namespace:")==0) {
8235 $TUnit_Funcs{$Version}{$Name} = 1;
8236 }
8237 }
8238 elsif($Type eq "x")
8239 {
8240 if(not $Scpe or index($Scpe, "namespace:")==0) {
8241 $TUnit_Vars{$Version}{$Name} = 1;
8242 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008243 }
8244 }
8245 close(CTAGS);
8246}
8247
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008248sub preChange($$)
8249{
8250 my ($HeaderPath, $IncStr) = @_;
8251
8252 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8253 my $Content = undef;
8254
8255 if($OStarget eq "windows"
8256 and get_dumpmachine($GCC_PATH)=~/mingw/i
8257 and $MinGWMode{$Version}!=-1)
8258 { # modify headers to compile by MinGW
8259 if(not $Content)
8260 { # preprocessing
8261 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8262 }
8263 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8264 { # __asm { ... }
8265 $MinGWMode{$Version}=1;
8266 }
8267 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8268 { # comments after preprocessing
8269 $MinGWMode{$Version}=1;
8270 }
8271 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8272 { # 0xffui8
8273 $MinGWMode{$Version}=1;
8274 }
8275
8276 if($MinGWMode{$Version}) {
8277 printMsg("INFO", "Using MinGW compatibility mode");
8278 }
8279 }
8280
8281 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8282 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8283 { # rename C++ keywords in C code
8284 # disable this code by -cpp-compatible option
8285 if(not $Content)
8286 { # preprocessing
8287 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8288 }
8289 my $RegExp_C = join("|", keys(%CppKeywords_C));
8290 my $RegExp_F = join("|", keys(%CppKeywords_F));
8291 my $RegExp_O = join("|", keys(%CppKeywords_O));
8292
8293 my $Detected = undef;
8294
8295 while($Content=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*(\,|\)|\;|\-\>|\.|\:\s*\d))/$1$2c99_$3$4/g)
8296 { # MATCH:
8297 # int foo(int new, int class, int (*new)(int));
8298 # unsigned private: 8;
8299 # DO NOT MATCH:
8300 # #pragma GCC visibility push(default)
8301 $CppMode{$Version} = 1;
8302 $Detected = "$1$2$3$4" if(not defined $Detected);
8303 }
8304 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8305 { # MATCH:
8306 # int delete(...);
8307 # int explicit(...);
8308 # DO NOT MATCH:
8309 # void operator delete(...)
8310 $CppMode{$Version} = 1;
8311 $Detected = "$1$2$3" if(not defined $Detected);
8312 }
8313 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8314 { # MATCH:
8315 # int bool;
8316 # DO NOT MATCH:
8317 # bool X;
8318 # return *this;
8319 # throw;
8320 $CppMode{$Version} = 1;
8321 $Detected = "$1$2$3" if(not defined $Detected);
8322 }
8323 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8324 { # MATCH:
8325 # int operator(...);
8326 # DO NOT MATCH:
8327 # int operator()(...);
8328 $CppMode{$Version} = 1;
8329 $Detected = "$1$2$3" if(not defined $Detected);
8330 }
8331 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8332 { # MATCH:
8333 # int foo(int operator);
8334 # int foo(int operator, int other);
8335 # DO NOT MATCH:
8336 # int operator,(...);
8337 $CppMode{$Version} = 1;
8338 $Detected = "$1$2$3" if(not defined $Detected);
8339 }
8340 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8341 { # MATCH:
8342 # int foo(gboolean *bool);
8343 # DO NOT MATCH:
8344 # void setTabEnabled(int index, bool);
8345 $CppMode{$Version} = 1;
8346 $Detected = "$1$2$3" if(not defined $Detected);
8347 }
8348 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8349 { # MATCH:
8350 # int foo(int* this);
8351 # int bar(int this);
8352 # int baz(int throw);
8353 # DO NOT MATCH:
8354 # foo(X, this);
8355 $CppMode{$Version} = 1;
8356 $Detected = "$1$2$3$4" if(not defined $Detected);
8357 }
8358 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8359 { # MATCH:
8360 # struct template {...};
8361 # extern template foo(...);
8362 $CppMode{$Version} = 1;
8363 $Detected = "$1$2" if(not defined $Detected);
8364 }
8365
8366 if($CppMode{$Version} == 1)
8367 {
8368 if($Debug)
8369 {
8370 $Detected=~s/\A\s+//g;
8371 printMsg("INFO", "Detected code: \"$Detected\"");
8372 }
8373 }
8374
8375 # remove typedef enum NAME NAME;
8376 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8377 my $N = 0;
8378 while($N<=$#FwdTypedefs-1)
8379 {
8380 my $S = $FwdTypedefs[$N];
8381 if($S eq $FwdTypedefs[$N+1])
8382 {
8383 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008384 $CppMode{$Version} = 1;
8385
8386 if($Debug) {
8387 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8388 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008389 }
8390 $N+=2;
8391 }
8392
8393 if($CppMode{$Version}==1) {
8394 printMsg("INFO", "Using C++ compatibility mode");
8395 }
8396 }
8397
8398 if($CppMode{$Version}==1
8399 or $MinGWMode{$Version}==1)
8400 {
8401 my $IPath = $TMP_DIR."/dump$Version.i";
8402 writeFile($IPath, $Content);
8403 return $IPath;
8404 }
8405
8406 return undef;
8407}
8408
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008409sub getDump()
8410{
8411 if(not $GCC_PATH) {
8412 exitStatus("Error", "internal error - GCC path is not set");
8413 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008414
8415 my @Headers = keys(%{$Registered_Headers{$Version}});
8416 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8417
8418 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8419
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008420 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008421 my $HeaderPath = $TmpHeaderPath;
8422
8423 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008424 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008425 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8426 {
8427 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008428 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008429 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008430 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008431 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8432 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008433 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008434 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008435 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008436 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8437 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8438 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008439 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008440 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008441
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008442 if($ExtraInfo)
8443 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008444 if($IncludeString) {
8445 writeFile($ExtraInfo."/include-string", $IncludeString);
8446 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008447 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8448 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008449
8450 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8451 {
8452 my $REDIR = "";
8453 foreach my $P1 (sort @Redirects) {
8454 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8455 }
8456 writeFile($ExtraInfo."/include-redirect", $REDIR);
8457 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008458 }
8459
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008460 if(not keys(%{$TargetHeaders{$Version}}))
8461 { # Target headers
8462 addTargetHeaders($Version);
8463 }
8464
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008465 # clean memory
8466 %RecursiveIncludes = ();
8467 %Header_Include_Prefix = ();
8468 %Header_Includes = ();
8469
8470 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008471 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008472 delete($Cache{"detect_header_includes"});
8473 delete($Cache{"selectSystemHeader"});
8474
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008475 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008476 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8477 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008478
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008479 if($ExtraInfo)
8480 { # extra information for other tools
8481 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8482 }
8483
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008484 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008485 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008486 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008487
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008488 if($COMMON_LANGUAGE{$Version} eq "C++") {
8489 checkCTags($Pre);
8490 }
8491
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008492 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8493 { # try to correct the preprocessor output
8494 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008495 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008496
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008497 if($COMMON_LANGUAGE{$Version} eq "C++")
8498 { # add classes and namespaces to the dump
8499 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008500 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008501 or $MinGWMode{$Version}==1) {
8502 $CHdump .= " -fpreprocessed";
8503 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008504 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008505 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008506 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008507 chdir($ORIG_DIR);
8508 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8509 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008510 my $Content = readFile($ClassDump);
8511 foreach my $ClassInfo (split(/\n\n/, $Content))
8512 {
8513 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8514 {
8515 my $CName = $1;
8516 next if($CName=~/\A(__|_objc_|_opaque_)/);
8517 $TUnit_NameSpaces{$Version}{$CName} = -1;
8518 if($CName=~/\A[\w:]+\Z/)
8519 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008520 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008521 }
8522 if($CName=~/(\w[\w:]*)::/)
8523 { # namespaces
8524 my $NS = $1;
8525 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8526 $TUnit_NameSpaces{$Version}{$NS} = 1;
8527 }
8528 }
8529 }
8530 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8531 { # read v-tables (advanced approach)
8532 my ($CName, $VTable) = ($1, $2);
8533 $ClassVTable_Content{$Version}{$CName} = $VTable;
8534 }
8535 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008536 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8537 { # add user-defined namespaces
8538 $TUnit_NameSpaces{$Version}{$NS} = 1;
8539 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008540 if($Debug)
8541 { # debug mode
8542 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008543 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008544 }
8545 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008546 }
8547
8548 # add namespaces and classes
8549 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8550 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008551 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008552 }
8553 # some GCC versions don't include class methods to the TU dump by default
8554 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008555 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008556 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8557 {
8558 next if($C_Structure{$CName});
8559 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008560 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008561 if(not $Force and $GCC_44
8562 and $OSgroup eq "linux")
8563 { # optimization for linux with GCC >= 4.4
8564 # disable this code by -force option
8565 if(index($CName, "::")!=-1)
8566 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008567 next;
8568 }
8569 }
8570 else
8571 {
8572 if($CName=~/\A(.+)::[^:]+\Z/
8573 and $TUnit_Classes{$Version}{$1})
8574 { # classes inside other classes
8575 next;
8576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008577 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008578 if(defined $TUnit_Funcs{$Version}{$CName})
8579 { # the same name for a function and type
8580 next;
8581 }
8582 if(defined $TUnit_Vars{$Version}{$CName})
8583 { # the same name for a variable and type
8584 next;
8585 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008586 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8587 }
8588 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008589 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008590 }
8591 }
8592 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8593 # create TU dump
8594 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008595 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008596 or $MinGWMode{$Version}==1) {
8597 $TUdump .= " -fpreprocessed";
8598 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008599 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008600 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8601 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008602 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008603 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008604 if($?)
8605 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008606 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008607 { # try to recompile
8608 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008609 if($CppMode{$Version}==1
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008610 and index($Errors, "c99_")!=-1)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008611 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008612 $CppMode{$Version}=-1;
8613 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008614 resetLogging($Version);
8615 $TMP_DIR = tempdir(CLEANUP=>1);
8616 return getDump();
8617 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008618 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008619 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008620 { # add auto preamble headers and try again
8621 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008622 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008623 foreach my $Num (0 .. $#Headers)
8624 {
8625 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008626 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8627 {
8628 push_U($Include_Preamble{$Version}, $Path);
8629 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008630 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008631 }
8632 resetLogging($Version);
8633 $TMP_DIR = tempdir(CLEANUP=>1);
8634 return getDump();
8635 }
8636 elsif($Cpp0xMode{$Version}!=-1
8637 and ($Errors=~/\Q-std=c++0x\E/
8638 or $Errors=~/is not a class or namespace/))
8639 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008640 if(check_gcc($GCC_PATH, "4.6"))
8641 {
8642 $Cpp0xMode{$Version}=-1;
8643 printMsg("INFO", "Enabling c++0x mode");
8644 resetLogging($Version);
8645 $TMP_DIR = tempdir(CLEANUP=>1);
8646 $CompilerOptions{$Version} .= " -std=c++0x";
8647 return getDump();
8648 }
8649 else {
8650 printMsg("WARNING", "Probably c++0x construction detected");
8651 }
8652
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008653 }
8654 elsif($MinGWMode{$Version}==1)
8655 { # disable MinGW mode and try again
8656 $MinGWMode{$Version}=-1;
8657 resetLogging($Version);
8658 $TMP_DIR = tempdir(CLEANUP=>1);
8659 return getDump();
8660 }
8661 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008662 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008663 else {
8664 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008666 printMsg("ERROR", "some errors occurred when compiling headers");
8667 printErrorLog($Version);
8668 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008669 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008670 }
8671 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008672 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008673 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008674
8675 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8676 return $TUs[0];
8677 }
8678 else
8679 {
8680 my $Msg = "can't compile header(s)";
8681 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8682 $Msg .= "\nDid you install G++?";
8683 }
8684 exitStatus("Cannot_Compile", $Msg);
8685 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008686}
8687
8688sub cmd_file($)
8689{
8690 my $Path = $_[0];
8691 return "" if(not $Path or not -e $Path);
8692 if(my $CmdPath = get_CmdPath("file")) {
8693 return `$CmdPath -b \"$Path\"`;
8694 }
8695 return "";
8696}
8697
8698sub getIncString($$)
8699{
8700 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008701 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008702 my $String = "";
8703 foreach (@{$ArrRef}) {
8704 $String .= " ".inc_opt($_, $Style);
8705 }
8706 return $String;
8707}
8708
8709sub getIncPaths(@)
8710{
8711 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008712 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008713 if($INC_PATH_AUTODETECT{$Version})
8714 { # auto-detecting dependencies
8715 my %Includes = ();
8716 foreach my $HPath (@HeaderPaths)
8717 {
8718 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8719 {
8720 if($Skip_Include_Paths{$Version}{$Dir}) {
8721 next;
8722 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008723 if($SystemRoot)
8724 {
8725 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8726 next;
8727 }
8728 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008729 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008730 }
8731 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008732 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008733 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008734 }
8735 }
8736 else
8737 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008738 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008739 }
8740 return \@IncPaths;
8741}
8742
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008743sub push_U($@)
8744{ # push unique
8745 if(my $Array = shift @_)
8746 {
8747 if(@_)
8748 {
8749 my %Exist = map {$_=>1} @{$Array};
8750 foreach my $Elem (@_)
8751 {
8752 if(not defined $Exist{$Elem})
8753 {
8754 push(@{$Array}, $Elem);
8755 $Exist{$Elem} = 1;
8756 }
8757 }
8758 }
8759 }
8760}
8761
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008762sub callPreprocessor($$$)
8763{
8764 my ($Path, $Inc, $LibVersion) = @_;
8765 return "" if(not $Path or not -f $Path);
8766 my $IncludeString=$Inc;
8767 if(not $Inc) {
8768 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8769 }
8770 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008771 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008772 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008773 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008774}
8775
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008776sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008777{ # native "find" is much faster than File::Find (~6x)
8778 # also the File::Find doesn't support --maxdepth N option
8779 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008780 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008781 return () if(not $Path or not -e $Path);
8782 if($OSgroup eq "windows")
8783 {
8784 my $DirCmd = get_CmdPath("dir");
8785 if(not $DirCmd) {
8786 exitStatus("Not_Found", "can't find \"dir\" command");
8787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008788 $Path = get_abs_path($Path);
8789 $Path = path_format($Path, $OSgroup);
8790 my $Cmd = $DirCmd." \"$Path\" /B /O";
8791 if($MaxDepth!=1) {
8792 $Cmd .= " /S";
8793 }
8794 if($Type eq "d") {
8795 $Cmd .= " /AD";
8796 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008797 elsif($Type eq "f") {
8798 $Cmd .= " /A-D";
8799 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008800 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008801 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008802 {
8803 if(not $UseRegex)
8804 { # FIXME: how to search file names in MS shell?
8805 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008806 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008807 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008808 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008809 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008810 }
8811 my @AbsPaths = ();
8812 foreach my $File (@Files)
8813 {
8814 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008815 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008816 }
8817 if($Type eq "f" and not -f $File)
8818 { # skip dirs
8819 next;
8820 }
8821 push(@AbsPaths, path_format($File, $OSgroup));
8822 }
8823 if($Type eq "d") {
8824 push(@AbsPaths, $Path);
8825 }
8826 return @AbsPaths;
8827 }
8828 else
8829 {
8830 my $FindCmd = get_CmdPath("find");
8831 if(not $FindCmd) {
8832 exitStatus("Not_Found", "can't find a \"find\" command");
8833 }
8834 $Path = get_abs_path($Path);
8835 if(-d $Path and -l $Path
8836 and $Path!~/\/\Z/)
8837 { # for directories that are symlinks
8838 $Path.="/";
8839 }
8840 my $Cmd = $FindCmd." \"$Path\"";
8841 if($MaxDepth) {
8842 $Cmd .= " -maxdepth $MaxDepth";
8843 }
8844 if($Type) {
8845 $Cmd .= " -type $Type";
8846 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008847 if($Name and not $UseRegex)
8848 { # wildcards
8849 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008850 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008851 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008852 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008853 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8854 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008855 my @Files = split(/\n/, $Res);
8856 if($Name and $UseRegex)
8857 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008858 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008859 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008860 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008861 }
8862}
8863
8864sub unpackDump($)
8865{
8866 my $Path = $_[0];
8867 return "" if(not $Path or not -e $Path);
8868 $Path = get_abs_path($Path);
8869 $Path = path_format($Path, $OSgroup);
8870 my ($Dir, $FileName) = separate_path($Path);
8871 my $UnpackDir = $TMP_DIR."/unpack";
8872 rmtree($UnpackDir);
8873 mkpath($UnpackDir);
8874 if($FileName=~s/\Q.zip\E\Z//g)
8875 { # *.zip
8876 my $UnzipCmd = get_CmdPath("unzip");
8877 if(not $UnzipCmd) {
8878 exitStatus("Not_Found", "can't find \"unzip\" command");
8879 }
8880 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008881 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008882 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008883 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008884 }
8885 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008886 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008887 if(not @Contents) {
8888 exitStatus("Error", "can't extract \'$Path\'");
8889 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008890 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008891 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008892 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008893 { # *.tar.gz
8894 if($OSgroup eq "windows")
8895 { # -xvzf option is not implemented in tar.exe (2003)
8896 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8897 my $TarCmd = get_CmdPath("tar");
8898 if(not $TarCmd) {
8899 exitStatus("Not_Found", "can't find \"tar\" command");
8900 }
8901 my $GzipCmd = get_CmdPath("gzip");
8902 if(not $GzipCmd) {
8903 exitStatus("Not_Found", "can't find \"gzip\" command");
8904 }
8905 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008906 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008907 if($?) {
8908 exitStatus("Error", "can't extract \'$Path\'");
8909 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008910 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008911 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008912 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008913 }
8914 chdir($ORIG_DIR);
8915 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008916 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008917 if(not @Contents) {
8918 exitStatus("Error", "can't extract \'$Path\'");
8919 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008920 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008921 }
8922 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008923 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008924 my $TarCmd = get_CmdPath("tar");
8925 if(not $TarCmd) {
8926 exitStatus("Not_Found", "can't find \"tar\" command");
8927 }
8928 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008929 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008930 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008931 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008932 }
8933 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008934 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008935 if(not @Contents) {
8936 exitStatus("Error", "can't extract \'$Path\'");
8937 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008938 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008939 }
8940 }
8941}
8942
8943sub createArchive($$)
8944{
8945 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008946 if(not $To) {
8947 $To = ".";
8948 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008949 if(not $Path or not -e $Path
8950 or not -d $To) {
8951 return "";
8952 }
8953 my ($From, $Name) = separate_path($Path);
8954 if($OSgroup eq "windows")
8955 { # *.zip
8956 my $ZipCmd = get_CmdPath("zip");
8957 if(not $ZipCmd) {
8958 exitStatus("Not_Found", "can't find \"zip\"");
8959 }
8960 my $Pkg = $To."/".$Name.".zip";
8961 unlink($Pkg);
8962 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008963 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008964 if($?)
8965 { # cannot allocate memory (or other problems with "zip")
8966 unlink($Path);
8967 exitStatus("Error", "can't pack the ABI dump: ".$!);
8968 }
8969 chdir($ORIG_DIR);
8970 unlink($Path);
8971 return $Pkg;
8972 }
8973 else
8974 { # *.tar.gz
8975 my $TarCmd = get_CmdPath("tar");
8976 if(not $TarCmd) {
8977 exitStatus("Not_Found", "can't find \"tar\"");
8978 }
8979 my $GzipCmd = get_CmdPath("gzip");
8980 if(not $GzipCmd) {
8981 exitStatus("Not_Found", "can't find \"gzip\"");
8982 }
8983 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8984 unlink($Pkg);
8985 chdir($From);
8986 system($TarCmd, "-czf", $Pkg, $Name);
8987 if($?)
8988 { # cannot allocate memory (or other problems with "tar")
8989 unlink($Path);
8990 exitStatus("Error", "can't pack the ABI dump: ".$!);
8991 }
8992 chdir($ORIG_DIR);
8993 unlink($Path);
8994 return $To."/".$Name.".tar.gz";
8995 }
8996}
8997
8998sub is_header_file($)
8999{
9000 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
9001 return $_[0];
9002 }
9003 return 0;
9004}
9005
9006sub is_not_header($)
9007{
9008 if($_[0]=~/\.\w+\Z/
9009 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
9010 return 1;
9011 }
9012 return 0;
9013}
9014
9015sub is_header($$$)
9016{
9017 my ($Header, $UserDefined, $LibVersion) = @_;
9018 return 0 if(-d $Header);
9019 if(-f $Header) {
9020 $Header = get_abs_path($Header);
9021 }
9022 else
9023 {
9024 if(is_abs($Header))
9025 { # incorrect absolute path
9026 return 0;
9027 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009028 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009029 $Header = $HPath;
9030 }
9031 else
9032 { # can't find header
9033 return 0;
9034 }
9035 }
9036 if($Header=~/\.\w+\Z/)
9037 { # have an extension
9038 return is_header_file($Header);
9039 }
9040 else
9041 {
9042 if($UserDefined==2)
9043 { # specified on the command line
9044 if(cmd_file($Header)!~/HTML|XML/i) {
9045 return $Header;
9046 }
9047 }
9048 elsif($UserDefined)
9049 { # specified in the XML-descriptor
9050 # header file without an extension
9051 return $Header;
9052 }
9053 else
9054 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009055 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009056 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009057 { # !~/HTML|XML|shared|dynamic/i
9058 return $Header;
9059 }
9060 }
9061 }
9062 return 0;
9063}
9064
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009065sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009066{
9067 my $LibVersion = $_[0];
9068 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9069 {
9070 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009071 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009072
9073 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9074 detect_recursive_includes($RegHeader, $LibVersion);
9075 }
9076
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009077 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9078 {
9079 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009080
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009081 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009082 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9083 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009084 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009085 }
9086 }
9087 }
9088}
9089
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009090sub familiarDirs($$)
9091{
9092 my ($D1, $D2) = @_;
9093 if($D1 eq $D2) {
9094 return 1;
9095 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009096
9097 my $U1 = index($D1, "/usr/");
9098 my $U2 = index($D2, "/usr/");
9099
9100 if($U1==0 and $U2!=0) {
9101 return 0;
9102 }
9103
9104 if($U2==0 and $U1!=0) {
9105 return 0;
9106 }
9107
9108 if(index($D2, $D1."/")==0) {
9109 return 1;
9110 }
9111
9112 # /usr/include/DIR
9113 # /home/user/DIR
9114
9115 my $DL = get_depth($D1);
9116
9117 my @Dirs1 = ($D1);
9118 while($DL - get_depth($D1)<=2
9119 and get_depth($D1)>=4
9120 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9121 push(@Dirs1, $D1);
9122 }
9123
9124 my @Dirs2 = ($D2);
9125 while(get_depth($D2)>=4
9126 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9127 push(@Dirs2, $D2);
9128 }
9129
9130 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009131 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009132 foreach my $P2 (@Dirs2)
9133 {
9134
9135 if($P1 eq $P2) {
9136 return 1;
9137 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009138 }
9139 }
9140 return 0;
9141}
9142
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009143sub readHeaders($)
9144{
9145 $Version = $_[0];
9146 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9147 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009148 if($Debug)
9149 { # debug mode
9150 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009151 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009152 }
9153 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009154}
9155
9156sub prepareTypes($)
9157{
9158 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009159 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009160 { # support for old ABI dumps
9161 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009162 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009163 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009164 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9165 if($TName=~/\A(\w+)::(\w+)/) {
9166 my ($P1, $P2) = ($1, $2);
9167 if($P1 eq $P2) {
9168 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009169 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009170 else {
9171 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9172 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009173 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009174 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009175 }
9176 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009177 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009178 { # support for old ABI dumps
9179 # V < 2.5: array size == "number of elements"
9180 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009181 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009182 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009183 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009184 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009185 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009186 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009187 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009188 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009189 $Size *= $Base{"Size"};
9190 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009191 }
9192 else
9193 { # array[] is a pointer
9194 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009195 }
9196 }
9197 }
9198 }
9199 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009200 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009201 { # support for old ABI dumps
9202 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009203 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009204 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009205 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009206 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009207 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009208 my %Type = get_Type($TypeId, $LibVersion);
9209 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9210 my %Type2 = get_Type($TypeId_2, $V2);
9211 if($Type{"Size"} ne $Type2{"Size"}) {
9212 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009213 }
9214 }
9215 }
9216 }
9217}
9218
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009219sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009220{
9221 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009222
9223 if(not keys(%{$SymbolInfo{$LibVersion}}))
9224 { # check if input is valid
9225 if(not $ExtendedCheck and not $CheckObjectsOnly)
9226 {
9227 if($CheckHeadersOnly) {
9228 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9229 }
9230 else {
9231 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9232 }
9233 }
9234 }
9235
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009236 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009237 if(not checkDump(1, "2.10")
9238 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009239 { # different formats
9240 $Remangle = 1;
9241 }
9242 if($CheckHeadersOnly)
9243 { # different languages
9244 if($UserLang)
9245 { # --lang=LANG for both versions
9246 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9247 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9248 {
9249 if($UserLang eq "C++")
9250 { # remangle symbols
9251 $Remangle = 1;
9252 }
9253 elsif($UserLang eq "C")
9254 { # remove mangling
9255 $Remangle = -1;
9256 }
9257 }
9258 }
9259 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009260
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009261 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009262 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009263 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009264 { # support for old ABI dumps
9265 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9266 {
9267 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9268 {
9269 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9270 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009271 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009272 if(defined $DVal and $DVal ne "")
9273 {
9274 if($TName eq "char") {
9275 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9276 }
9277 elsif($TName eq "bool") {
9278 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9279 }
9280 }
9281 }
9282 }
9283 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009284 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009285 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009286 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9287 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009288 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009289 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9290 # + support for old ABI dumps
9291 next;
9292 }
9293 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009294 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009295 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009296 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009297 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009298
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009299 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009300 if(not checkDump(1, "2.12")
9301 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009302 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009303 if($ShortName eq "operator>>")
9304 {
9305 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9306 { # corrected mangling of operator>>
9307 $SRemangle = 1;
9308 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009309 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009310 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9311 {
9312 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9313 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9314 { # corrected mangling of const global data
9315 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9316 # and incorrectly mangled by old ACC versions
9317 $SRemangle = 1;
9318 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009319 }
9320 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009321 if(not $CheckHeadersOnly)
9322 { # support for old ABI dumps
9323 if(not checkDump(1, "2.17")
9324 or not checkDump(2, "2.17"))
9325 {
9326 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9327 {
9328 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9329 {
9330 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9331 {
9332 $MnglName = $ShortName;
9333 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9334 }
9335 }
9336 }
9337 }
9338 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009339 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009340 { # support for old ABI dumps: some symbols are not mangled in old dumps
9341 # mangle both sets of symbols (old and new)
9342 # NOTE: remangling all symbols by the same mangler
9343 if($MnglName=~/\A_ZN(V|)K/)
9344 { # mangling may be incorrect on old ABI dumps
9345 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009346 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009347 }
9348 if($MnglName=~/\A_ZN(K|)V/)
9349 { # mangling may be incorrect on old ABI dumps
9350 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009351 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009352 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009353 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9354 or (not $ClassID and $CheckHeadersOnly)
9355 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9356 { # support for old ABI dumps, GCC >= 4.0
9357 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009358 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009359 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009360 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009361 $MangledNames{$LibVersion}{$MnglName} = 1;
9362 }
9363 }
9364 }
9365 elsif($Remangle==-1)
9366 { # remove mangling
9367 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009368 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009370 if(not $MnglName) {
9371 next;
9372 }
9373 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9374 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009375 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9376
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009377 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009378 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009379 { # support for old dumps
9380 # add "Volatile" attribute
9381 if($MnglName=~/_Z(K|)V/) {
9382 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9383 }
9384 }
9385 # symbol and its symlink have same signatures
9386 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009387 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009388 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009389
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009390 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9391 {
9392 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9393 if($SymVer{$LibVersion}{$Alias}) {
9394 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9395 }
9396 }
9397
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009398 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009399 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009400 }
9401 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9402 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9403 }
9404 if($ExtendedCheck)
9405 { # --ext option
9406 addExtension($LibVersion);
9407 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009408
9409 # clean memory
9410 delete($SymbolInfo{$LibVersion});
9411
9412 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009413 { # detect allocable classes with public exported constructors
9414 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009415 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009416 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009417 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009418 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009419 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9420 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009421 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009422 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009423 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009424 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009425 $AllocableClass{$LibVersion}{$ClassName} = 1;
9426 }
9427 }
9428 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009429 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009430 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009431 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009432 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009433 if($CheckHeadersOnly)
9434 {
9435 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9436 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9437 { # all symbols except non-virtual inline
9438 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9439 }
9440 }
9441 else {
9442 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009443 }
9444 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009445 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009446 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009447 }
9448 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009449 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009450 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009451 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009452 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009453 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009454 if(defined $Base{"Type"}
9455 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009456 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009457 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009458 if($Name=~/<([^<>\s]+)>/)
9459 {
9460 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9461 $ReturnedClass{$LibVersion}{$Tid} = 1;
9462 }
9463 }
9464 else {
9465 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9466 }
9467 }
9468 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009469 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009470 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009471 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009472 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009473 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009474 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009475 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009476 if($Base{"Type"}=~/Struct|Class/)
9477 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009478 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009479 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9480 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009481 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009482 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009483 }
9484 }
9485 }
9486 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009487
9488 # mapping {short name => symbols}
9489 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009490 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009491 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009492 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009493 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009494 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009495 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009496 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009497 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9498 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009499 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009500 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009501 }
9502 }
9503 }
9504 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009505
9506 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009507 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009508 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009509 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009510 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009511 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9512 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009513 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009514 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009515 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009516 $ClassNames{$LibVersion}{$TName} = 1;
9517 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009518 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009519 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9520 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009521 }
9522 }
9523 }
9524 }
9525 }
9526}
9527
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009528sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009529{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009530 my ($Tid, $LibVersion) = @_;
9531 if(not $Tid) {
9532 return $Tid;
9533 }
9534
9535 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9536 {
9537 if($TName_Tid{$LibVersion}{$Name}) {
9538 return $TName_Tid{$LibVersion}{$Name};
9539 }
9540 }
9541
9542 return $Tid;
9543}
9544
9545sub register_SymbolUsage($$$)
9546{
9547 my ($InfoId, $UsedType, $LibVersion) = @_;
9548
9549 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9550 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9551 {
9552 register_TypeUsage($RTid, $UsedType, $LibVersion);
9553 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9554 }
9555 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9556 {
9557 register_TypeUsage($FCid, $UsedType, $LibVersion);
9558 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9559
9560 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9561 { # register "this" pointer
9562 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9563 }
9564 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9565 { # register "this" pointer (const method)
9566 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9567 }
9568 }
9569 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9570 {
9571 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9572 {
9573 register_TypeUsage($PTid, $UsedType, $LibVersion);
9574 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9575 }
9576 }
9577 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9578 {
9579 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9580 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9581 register_TypeUsage($TTid, $UsedType, $LibVersion);
9582 }
9583 }
9584}
9585
9586sub register_TypeUsage($$$)
9587{
9588 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009589 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009590 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009591 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009592 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009593 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009594 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009595 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009596
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009597 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009598 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009599 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009600 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009601 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009602 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9603 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9604 }
9605 }
9606
9607 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9608 {
9609 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009610 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009611 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009612 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9613 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009614 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009615 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9616 {
9617 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9618 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009619 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009620 }
9621 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009622 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009623 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009624 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009625 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9626 {
9627 register_TypeUsage($MTid, $UsedType, $LibVersion);
9628 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009629 }
9630 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009631 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009632 or $TInfo{"Type"} eq "MethodPtr"
9633 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009634 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009635 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009636 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009637 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009638 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009639 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009640 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9641 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009642 }
9643 }
9644 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009645 if($TInfo{"Type"} eq "FieldPtr")
9646 {
9647 if(my $RTid = $TInfo{"Return"}) {
9648 register_TypeUsage($RTid, $UsedType, $LibVersion);
9649 }
9650 if(my $CTid = $TInfo{"Class"}) {
9651 register_TypeUsage($CTid, $UsedType, $LibVersion);
9652 }
9653 }
9654 if($TInfo{"Type"} eq "MethodPtr")
9655 {
9656 if(my $CTid = $TInfo{"Class"}) {
9657 register_TypeUsage($CTid, $UsedType, $LibVersion);
9658 }
9659 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009660 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009661 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009662 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009663 $UsedType->{$TypeId} = 1;
9664 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9665 {
9666 register_TypeUsage($BTid, $UsedType, $LibVersion);
9667 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9668 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009669 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009670 else
9671 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9672 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009673 }
9674 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009675}
9676
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009677sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009678{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009679 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9680
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009681 if($Level eq "Dump")
9682 {
9683 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9684 { # TODO: check if this symbol is from
9685 # base classes of other target symbols
9686 return 1;
9687 }
9688 }
9689
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009690 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9691 { # stdc++ interfaces
9692 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009693 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009694
9695 my $Target = 0;
9696 if(my $Header = $SInfo->{"Header"}) {
9697 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9698 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009699 if($ExtendedCheck)
9700 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009701 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009702 $Target = 1;
9703 }
9704 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009705 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009706 {
9707 if($Target)
9708 {
9709 if($Level eq "Dump")
9710 { # dumped
9711 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009712 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009713 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009714 return 1;
9715 }
9716 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009717 else {
9718 return 1;
9719 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009720 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009721 elsif($Level eq "Source")
9722 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009723 return 1;
9724 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009725 elsif($Level eq "Binary")
9726 { # checked
9727 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9728 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9729 return 1;
9730 }
9731 }
9732 }
9733 }
9734 else
9735 { # library is available
9736 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9737 { # exported symbols
9738 return 1;
9739 }
9740 if($Level eq "Dump")
9741 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009742 if($BinaryOnly)
9743 {
9744 if($SInfo->{"Data"})
9745 {
9746 if($Target) {
9747 return 1;
9748 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009749 }
9750 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009751 else
9752 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009753 if($Target) {
9754 return 1;
9755 }
9756 }
9757 }
9758 elsif($Level eq "Source")
9759 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009760 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
9761 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009762 { # skip LOCAL symbols
9763 if($Target) {
9764 return 1;
9765 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009766 }
9767 }
9768 elsif($Level eq "Binary")
9769 { # checked
9770 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9771 {
9772 if($Target) {
9773 return 1;
9774 }
9775 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009776 }
9777 }
9778 return 0;
9779}
9780
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009781sub cleanDump($)
9782{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009783 my $LibVersion = $_[0];
9784 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9785 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009786 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9787 {
9788 delete($SymbolInfo{$LibVersion}{$InfoId});
9789 next;
9790 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009791 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009792 if(not $MnglName)
9793 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009794 delete($SymbolInfo{$LibVersion}{$InfoId});
9795 next;
9796 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009797 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009798 if(not $ShortName)
9799 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009800 delete($SymbolInfo{$LibVersion}{$InfoId});
9801 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009802 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009803 if($MnglName eq $ShortName)
9804 { # remove duplicate data
9805 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009806 }
9807 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9808 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9809 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009810 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9811 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9812 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009813 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009814 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009815 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009816 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9817 {
9818 delete($TypeInfo{$LibVersion}{$Tid});
9819 next;
9820 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009821 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009822 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009823 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009824 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9825 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9826 }
9827 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009828 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9829 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9830 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009831 }
9832}
9833
9834sub selectType($$)
9835{
9836 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009837
9838 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9839 {
9840 if(defined $TypeInfo{$LibVersion}{$Dupl})
9841 {
9842 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9843 { # duplicate
9844 return 0;
9845 }
9846 }
9847 }
9848
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009849 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9850 {
9851 if(not isBuiltIn($THeader))
9852 {
9853 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009854 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009855 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9856 {
9857 if(is_target_header($THeader, $LibVersion))
9858 { # from target headers
9859 if(not selfTypedef($Tid, $LibVersion)) {
9860 return 1;
9861 }
9862 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009863 }
9864 }
9865 }
9866 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009867 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009868}
9869
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009870sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009871{ # remove unused data types from the ABI dump
9872 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009873
9874 my %UsedType = ();
9875
9876 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009877 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009878 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009879 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009880 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009881 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009882 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009883 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009884 next;
9885 }
9886
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009887 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009888 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009889 if(selectType($Tid, $LibVersion))
9890 {
9891 my %Tree = ();
9892 register_TypeUsage($Tid, \%Tree, $LibVersion);
9893
9894 my $Tmpl = 0;
9895 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9896 {
9897 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9898 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9899 {
9900 $Tmpl = 1;
9901 last;
9902 }
9903 }
9904 if(not $Tmpl)
9905 {
9906 foreach (keys(%Tree)) {
9907 $UsedType{$_} = 1;
9908 }
9909 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009910 }
9911 }
9912 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009913
9914 my %Delete = ();
9915
9916 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009917 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009918 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009919 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009920 next;
9921 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009922
9923 if($Kind eq "Extra")
9924 {
9925 my %Tree = ();
9926 register_TypeUsage($Tid, \%Tree, $LibVersion);
9927
9928 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9929 {
9930 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9931 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9932 {
9933 $Delete{$Tid} = 1;
9934 last;
9935 }
9936 }
9937 }
9938 else
9939 {
9940 # remove type
9941 delete($TypeInfo{$LibVersion}{$Tid});
9942 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009943 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009944
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009945 if($Kind eq "Extra")
9946 { # remove duplicates
9947 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9948 {
9949 if($UsedType{$Tid})
9950 { # All & Extended
9951 next;
9952 }
9953
9954 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9955
9956 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9957 delete($TypeInfo{$LibVersion}{$Tid});
9958 }
9959 }
9960 }
9961
9962 foreach my $Tid (keys(%Delete))
9963 {
9964 delete($TypeInfo{$LibVersion}{$Tid});
9965 }
9966}
9967
9968sub check_Completeness($$)
9969{
9970 my ($Info, $LibVersion) = @_;
9971
9972 # data types
9973 if(defined $Info->{"Memb"})
9974 {
9975 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9976 {
9977 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9978 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9979 }
9980 }
9981 }
9982 if(defined $Info->{"Base"})
9983 {
9984 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9985 check_TypeInfo($Bid, $LibVersion);
9986 }
9987 }
9988 if(defined $Info->{"BaseType"}) {
9989 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9990 }
9991 if(defined $Info->{"TParam"})
9992 {
9993 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9994 {
9995 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9996 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9997 next;
9998 }
9999 if($TName eq "_BoolType") {
10000 next;
10001 }
10002 if($TName=~/\Asizeof\(/) {
10003 next;
10004 }
10005 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10006 check_TypeInfo($Tid, $LibVersion);
10007 }
10008 else
10009 {
10010 if(defined $Debug) {
10011 printMsg("WARNING", "missed type $TName");
10012 }
10013 }
10014 }
10015 }
10016
10017 # symbols
10018 if(defined $Info->{"Param"})
10019 {
10020 foreach my $Pos (keys(%{$Info->{"Param"}}))
10021 {
10022 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10023 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10024 }
10025 }
10026 }
10027 if(defined $Info->{"Return"}) {
10028 check_TypeInfo($Info->{"Return"}, $LibVersion);
10029 }
10030 if(defined $Info->{"Class"}) {
10031 check_TypeInfo($Info->{"Class"}, $LibVersion);
10032 }
10033}
10034
10035sub check_TypeInfo($$)
10036{
10037 my ($Tid, $LibVersion) = @_;
10038
10039 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10040 return;
10041 }
10042 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10043
10044 if(defined $TypeInfo{$LibVersion}{$Tid})
10045 {
10046 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10047 printMsg("ERROR", "missed type name ($Tid)");
10048 }
10049 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10050 }
10051 else {
10052 printMsg("ERROR", "missed type id $Tid");
10053 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010054}
10055
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010056sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010057{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010058 my ($TypeId, $LibVersion) = @_;
10059 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010060 if($Type{"Type"} eq "Typedef")
10061 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010062 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010063 if($Base{"Type"}=~/Class|Struct/)
10064 {
10065 if($Type{"Name"} eq $Base{"Name"}) {
10066 return 1;
10067 }
10068 elsif($Type{"Name"}=~/::(\w+)\Z/)
10069 {
10070 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10071 { # QPointer<QWidget>::QPointer
10072 return 1;
10073 }
10074 }
10075 }
10076 }
10077 return 0;
10078}
10079
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010080sub addExtension($)
10081{
10082 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010083 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010084 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010085 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010086 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010087 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10088 $TName=~s/\A(struct|union|class|enum) //;
10089 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010090
10091 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10092 "Header" => "extended.h",
10093 "ShortName" => $Symbol,
10094 "MnglName" => $Symbol,
10095 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10096 );
10097
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010098 $ExtendedSymbols{$Symbol} = 1;
10099 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10100 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010101 }
10102 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010103 $ExtendedSymbols{"external_func_0"} = 1;
10104 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10105 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010106}
10107
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010108sub findMethod($$$)
10109{
10110 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010111 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010112 {
10113 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10114 return $VirtMethodInClass;
10115 }
10116 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10117 return $VirtMethodInBaseClasses;
10118 }
10119 }
10120 return "";
10121}
10122
10123sub findMethod_Class($$$)
10124{
10125 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010126 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010127 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10128 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10129 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10130 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10131 { # search for interface with the same parameters suffix (overridden)
10132 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10133 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010134 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10135 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010136 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10137 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010138 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10139 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10140 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10141 return $Candidate;
10142 }
10143 }
10144 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010145 else
10146 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010147 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10148 return $Candidate;
10149 }
10150 }
10151 }
10152 }
10153 return "";
10154}
10155
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010156sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010157{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010158 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010159 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010160 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010161 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10162 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010163 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010164 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010165 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010166 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10167 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010168 { # pure virtual D2-destructors are marked as "virt" in the dump
10169 # virtual D2-destructors are NOT marked as "virt" in the dump
10170 # both destructors are not presented in the v-table
10171 next;
10172 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010173 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010174 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10175 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010176 }
10177}
10178
10179sub registerOverriding($)
10180{
10181 my $LibVersion = $_[0];
10182 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010183 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010184 foreach my $ClassName (@Classes)
10185 {
10186 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10187 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010188 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10189 { # pure virtuals
10190 next;
10191 }
10192 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10193 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010194 {
10195 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10196 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10197 { # both overridden virtual methods
10198 # and implemented pure virtual methods
10199 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10200 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10201 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10202 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010203 }
10204 }
10205 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10206 delete($VirtualTable{$LibVersion}{$ClassName});
10207 }
10208 }
10209}
10210
10211sub setVirtFuncPositions($)
10212{
10213 my $LibVersion = $_[0];
10214 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10215 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010216 my ($Num, $Rel) = (1, 0);
10217
10218 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010219 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010220 if($UsedDump{$LibVersion}{"DWARF"}) {
10221 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10222 }
10223 else {
10224 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10225 }
10226 foreach my $VirtFunc (@Funcs)
10227 {
10228 if($UsedDump{$LibVersion}{"DWARF"}) {
10229 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10230 }
10231 else {
10232 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10233 }
10234
10235 # set relative positions
10236 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10237 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10238 { # relative position excluding added and removed virtual functions
10239 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10240 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10241 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010243 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010244 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010245 }
10246 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010247 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010248 {
10249 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010250 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010251 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010252 }
10253 }
10254}
10255
10256sub get_sub_classes($$$)
10257{
10258 my ($ClassId, $LibVersion, $Recursive) = @_;
10259 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10260 my @Subs = ();
10261 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10262 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010263 if($Recursive)
10264 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010265 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10266 push(@Subs, $SubSubId);
10267 }
10268 }
10269 push(@Subs, $SubId);
10270 }
10271 return @Subs;
10272}
10273
10274sub get_base_classes($$$)
10275{
10276 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010277 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010278 return () if(not defined $ClassType{"Base"});
10279 my @Bases = ();
10280 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10281 keys(%{$ClassType{"Base"}}))
10282 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010283 if($Recursive)
10284 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010285 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10286 push(@Bases, $SubBaseId);
10287 }
10288 }
10289 push(@Bases, $BaseId);
10290 }
10291 return @Bases;
10292}
10293
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010294sub getVTable_Model($$)
10295{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010296 my ($ClassId, $LibVersion) = @_;
10297 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10298 my @Elements = ();
10299 foreach my $BaseId (@Bases, $ClassId)
10300 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010301 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010302 {
10303 if(defined $VirtualTable{$LibVersion}{$BName})
10304 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010305 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10306 if($UsedDump{$LibVersion}{"DWARF"}) {
10307 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10308 }
10309 else {
10310 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10311 }
10312 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010313 push(@Elements, $VFunc);
10314 }
10315 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010316 }
10317 }
10318 return @Elements;
10319}
10320
10321sub getVShift($$)
10322{
10323 my ($ClassId, $LibVersion) = @_;
10324 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10325 my $VShift = 0;
10326 foreach my $BaseId (@Bases)
10327 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010328 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010329 {
10330 if(defined $VirtualTable{$LibVersion}{$BName}) {
10331 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10332 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010333 }
10334 }
10335 return $VShift;
10336}
10337
10338sub getShift($$)
10339{
10340 my ($ClassId, $LibVersion) = @_;
10341 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10342 my $Shift = 0;
10343 foreach my $BaseId (@Bases)
10344 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010345 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010346 {
10347 if($Size!=1)
10348 { # not empty base class
10349 $Shift+=$Size;
10350 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010351 }
10352 }
10353 return $Shift;
10354}
10355
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010356sub getVTable_Size($$)
10357{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010358 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010359 my $Size = 0;
10360 # three approaches
10361 if(not $Size)
10362 { # real size
10363 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10364 $Size = keys(%VTable);
10365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010366 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010367 if(not $Size)
10368 { # shared library symbol size
10369 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10370 $Size /= $WORD_SIZE{$LibVersion};
10371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010372 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010373 if(not $Size)
10374 { # model size
10375 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10376 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10377 }
10378 }
10379 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010380}
10381
10382sub isCopyingClass($$)
10383{
10384 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010385 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010386}
10387
10388sub isLeafClass($$)
10389{
10390 my ($ClassId, $LibVersion) = @_;
10391 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10392}
10393
10394sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010395{ # check structured type for public fields
10396 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010397}
10398
10399sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010400{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010401 my ($TypePtr, $Skip, $Start, $End) = @_;
10402 return 0 if(not $TypePtr);
10403 if($End==-1) {
10404 $End = keys(%{$TypePtr->{"Memb"}})-1;
10405 }
10406 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10407 {
10408 if($Skip and $Skip->{$MemPos})
10409 { # skip removed/added fields
10410 next;
10411 }
10412 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10413 {
10414 if(isPublic($TypePtr, $MemPos)) {
10415 return ($MemPos+1);
10416 }
10417 }
10418 }
10419 return 0;
10420}
10421
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010422sub isReserved($)
10423{ # reserved fields == private
10424 my $MName = $_[0];
10425 if($MName=~/reserved|padding|f_spare/i) {
10426 return 1;
10427 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010428 if($MName=~/\A[_]*(spare|pad|unused)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010429 return 1;
10430 }
10431 if($MName=~/(pad\d+)/i) {
10432 return 1;
10433 }
10434 return 0;
10435}
10436
10437sub isPublic($$)
10438{
10439 my ($TypePtr, $FieldPos) = @_;
10440 return 0 if(not $TypePtr);
10441 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10442 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10443 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10444 { # by name in C language
10445 # FIXME: add other methods to detect private members
10446 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10447 if($MName=~/priv|abidata|parent_object/i)
10448 { # C-styled private data
10449 return 0;
10450 }
10451 if(lc($MName) eq "abi")
10452 { # ABI information/reserved field
10453 return 0;
10454 }
10455 if(isReserved($MName))
10456 { # reserved fields
10457 return 0;
10458 }
10459 return 1;
10460 }
10461 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10462 { # by access in C++ language
10463 return 1;
10464 }
10465 return 0;
10466}
10467
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010468sub getVTable_Real($$)
10469{
10470 my ($ClassName, $LibVersion) = @_;
10471 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10472 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010473 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010474 if(defined $Type{"VTable"}) {
10475 return %{$Type{"VTable"}};
10476 }
10477 }
10478 return ();
10479}
10480
10481sub cmpVTables($)
10482{
10483 my $ClassName = $_[0];
10484 my $Res = cmpVTables_Real($ClassName, 1);
10485 if($Res==-1) {
10486 $Res = cmpVTables_Model($ClassName);
10487 }
10488 return $Res;
10489}
10490
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010491sub cmpVTables_Model($)
10492{
10493 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010494 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010495 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010496 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010497 return 1;
10498 }
10499 }
10500 return 0;
10501}
10502
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010503sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010504{
10505 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010506 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10507 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010508 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010509 my %VTable_Old = getVTable_Real($ClassName, 1);
10510 my %VTable_New = getVTable_Real($ClassName, 2);
10511 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010512 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010513 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010514 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010515 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010516 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10517 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010518 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010519 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010520 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010521 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010522 my $Entry1 = $VTable_Old{$Offset};
10523 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010524 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010525 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010526 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010527 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010528 $Entry1 = simpleVEntry($Entry1);
10529 $Entry2 = simpleVEntry($Entry2);
10530 if($Entry1 ne $Entry2)
10531 { # register as changed
10532 if($Entry1=~/::([^:]+)\Z/)
10533 {
10534 my $M1 = $1;
10535 if($Entry2=~/::([^:]+)\Z/)
10536 {
10537 my $M2 = $1;
10538 if($M1 eq $M2)
10539 { # overridden
10540 next;
10541 }
10542 }
10543 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010544 if(differentDumps("G"))
10545 {
10546 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10547 {
10548 # GCC 4.6.1: -0x00000000000000010
10549 # GCC 4.7.0: -16
10550 next;
10551 }
10552 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010553 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010554 }
10555 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010556 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010557}
10558
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010559sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010560{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010561 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010562 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10563 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010564 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010565 { # already registered
10566 next;
10567 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010568 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010569 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010570 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010571 foreach my $Symbol (@Affected)
10572 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010573 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010574 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010575 "Target"=>$ClassName);
10576 }
10577 }
10578 }
10579}
10580
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010581sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010582{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010583 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010584 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010585 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010586 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010587 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010588 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010589 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010590 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010591 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010592 if($TName_Tid{1}{$ClassName}
10593 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010594 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010595 if(defined $CompleteSignature{1}{$Symbol}
10596 and $CompleteSignature{1}{$Symbol}{"Virt"})
10597 { # override some method in v.1
10598 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010599 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010600 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010601 }
10602 }
10603 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010604 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010605 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010606 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010607 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010608 if($TName_Tid{2}{$ClassName}
10609 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010610 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010611 if(defined $CompleteSignature{2}{$Symbol}
10612 and $CompleteSignature{2}{$Symbol}{"Virt"})
10613 { # override some method in v.2
10614 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010615 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010616 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010617 }
10618 }
10619 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010620 if($Level eq "Binary")
10621 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010622 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010623 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10624 { # check replacements, including pure virtual methods
10625 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10626 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010627 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010628 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10629 if($AddedPos==$RemovedPos)
10630 {
10631 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10632 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10633 last; # other methods will be reported as "added" or "removed"
10634 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010635 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010636 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10637 {
10638 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10639 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010640 next;
10641 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010642 my $ProblemType = "Virtual_Replacement";
10643 my @Affected = ($RemovedVFunc);
10644 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10645 { # pure methods
10646 if(not isUsedClass($ClassId, 1, $Level))
10647 { # not a parameter of some exported method
10648 next;
10649 }
10650 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010651
10652 # affected all methods (both virtual and non-virtual ones)
10653 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10654 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010655 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010656 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010657 foreach my $AffectedInt (@Affected)
10658 {
10659 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10660 { # affected exported methods only
10661 next;
10662 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010663 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10664 next;
10665 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010666 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10667 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010668 "Target"=>get_Signature($AddedVFunc, 2),
10669 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10670 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010671 }
10672 }
10673 }
10674 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010675 if(not checkDump(1, "2.0")
10676 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010677 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010678 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010679 return;
10680 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010681 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010682 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010683 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010684 next if(not $ClassId_Old);
10685 if(not isCreatable($ClassId_Old, 1))
10686 { # skip classes without public constructors (including auto-generated)
10687 # example: class has only a private exported or private inline constructor
10688 next;
10689 }
10690 if($ClassName=~/>/)
10691 { # skip affected template instances
10692 next;
10693 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010694 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010695 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010696 if(not $ClassId_New) {
10697 next;
10698 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010699 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010700 if($Class_New{"Type"}!~/Class|Struct/)
10701 { # became typedef
10702 if($Level eq "Binary") {
10703 next;
10704 }
10705 if($Level eq "Source")
10706 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010707 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010708 if($Class_New{"Type"}!~/Class|Struct/) {
10709 next;
10710 }
10711 $ClassId_New = $Class_New{"Tid"};
10712 }
10713 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010714 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10715 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 +040010716
10717 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10718 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10719
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010720 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010721 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10722 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010723 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10724 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010725 my $Shift_Old = getShift($ClassId_Old, 1);
10726 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010727 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010728 my ($Added, $Removed) = (0, 0);
10729 my @StableBases_Old = ();
10730 foreach my $BaseId (@Bases_Old)
10731 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010732 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010733 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010734 push(@StableBases_Old, $BaseId);
10735 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010736 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010737 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010738 { # removed base
10739 # excluding namespace::SomeClass to SomeClass renaming
10740 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010741 if($Level eq "Binary")
10742 { # Binary-level
10743 if($Shift_Old ne $Shift_New)
10744 { # affected fields
10745 if(havePubFields(\%Class_Old)) {
10746 $ProblemKind .= "_And_Shift";
10747 }
10748 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10749 $ProblemKind .= "_And_Size";
10750 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010751 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010752 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10753 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010754 { # affected v-table
10755 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010756 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010757 }
10758 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010759 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010760 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10761 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010762 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10763 {
10764 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10765 if($ProblemKind=~/VTable/) {
10766 $VTableChanged_M{$SubName}=1;
10767 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010768 }
10769 }
10770 foreach my $Interface (@Affected)
10771 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010772 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10773 next;
10774 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010775 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010776 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010777 "Target"=>$BaseName,
10778 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10779 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10780 "Shift"=>abs($Shift_New-$Shift_Old) );
10781 }
10782 $Removed+=1;
10783 }
10784 }
10785 my @StableBases_New = ();
10786 foreach my $BaseId (@Bases_New)
10787 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010788 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010789 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010790 push(@StableBases_New, $BaseId);
10791 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010792 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010793 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010794 { # added base
10795 # excluding namespace::SomeClass to SomeClass renaming
10796 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010797 if($Level eq "Binary")
10798 { # Binary-level
10799 if($Shift_Old ne $Shift_New)
10800 { # affected fields
10801 if(havePubFields(\%Class_Old)) {
10802 $ProblemKind .= "_And_Shift";
10803 }
10804 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10805 $ProblemKind .= "_And_Size";
10806 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010807 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010808 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10809 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010810 { # affected v-table
10811 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010812 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010813 }
10814 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010815 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010816 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10817 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010818 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10819 {
10820 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10821 if($ProblemKind=~/VTable/) {
10822 $VTableChanged_M{$SubName}=1;
10823 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010824 }
10825 }
10826 foreach my $Interface (@Affected)
10827 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010828 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10829 next;
10830 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010831 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010832 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010833 "Target"=>$BaseName,
10834 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10835 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10836 "Shift"=>abs($Shift_New-$Shift_Old) );
10837 }
10838 $Added+=1;
10839 }
10840 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010841 if($Level eq "Binary")
10842 { # Binary-level
10843 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010844 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10845 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010846 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010847 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010848 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010849 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010850 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010851 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10852 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010853 if($NewPos!=$OldPos)
10854 { # changed position of the base class
10855 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010856 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010857 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10858 next;
10859 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010860 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10861 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010862 "Target"=>$BaseName,
10863 "Old_Value"=>$OldPos-1,
10864 "New_Value"=>$NewPos-1 );
10865 }
10866 }
10867 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10868 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10869 { # became non-virtual base
10870 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10871 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010872 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10873 next;
10874 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010875 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10876 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010877 "Target"=>$BaseName );
10878 }
10879 }
10880 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10881 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10882 { # became virtual base
10883 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10884 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010885 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10886 next;
10887 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010888 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10889 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010890 "Target"=>$BaseName );
10891 }
10892 }
10893 }
10894 }
10895 # detect size changes in base classes
10896 if($Shift_Old!=$Shift_New)
10897 { # size of allocable class
10898 foreach my $BaseId (@StableBases_Old)
10899 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010900 my %BaseType = get_Type($BaseId, 1);
10901 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010902 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010903 if($Size_Old ne $Size_New
10904 and $Size_Old and $Size_New)
10905 {
10906 my $ProblemType = "";
10907 if(isCopyingClass($BaseId, 1)) {
10908 $ProblemType = "Size_Of_Copying_Class";
10909 }
10910 elsif($AllocableClass{1}{$BaseType{"Name"}})
10911 {
10912 if($Size_New>$Size_Old)
10913 { # increased size
10914 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010915 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010916 else
10917 { # decreased size
10918 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10919 if(not havePubFields(\%Class_Old))
10920 { # affected class has no public members
10921 next;
10922 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010923 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010924 }
10925 next if(not $ProblemType);
10926 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10927 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010928 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10929 next;
10930 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010931 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10932 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010933 "Target"=>$BaseType{"Name"},
10934 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10935 "New_Size"=>$Size_New*$BYTE_SIZE );
10936 }
10937 }
10938 }
10939 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010940 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010941 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010942 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010943 { # compare virtual tables size in base classes
10944 my $VShift_Old = getVShift($ClassId_Old, 1);
10945 my $VShift_New = getVShift($ClassId_New, 2);
10946 if($VShift_Old ne $VShift_New)
10947 { # changes in the base class or changes in the list of base classes
10948 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10949 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10950 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010951 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010952 foreach my $BaseId (@AllBases_Old)
10953 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010954 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010955 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010956 { # lost base
10957 next;
10958 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010959 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10960 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010961 if($VSize_Old!=$VSize_New)
10962 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010963 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010964 { # TODO: affected non-virtual methods?
10965 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010966 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10967 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010968 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010969 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010970 { # skip interfaces that have not changed the absolute virtual position
10971 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010972 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010973 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10974 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010975 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010976 $VTableChanged_M{$BaseType{"Name"}} = 1;
10977 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010978 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10979 { # the reason of the layout change: added virtual functions
10980 next if($VirtualReplacement{$VirtFunc});
10981 my $ProblemType = "Added_Virtual_Method";
10982 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10983 $ProblemType = "Added_Pure_Virtual_Method";
10984 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010985 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010986 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010987 "Target"=>get_Signature($VirtFunc, 2) );
10988 }
10989 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10990 { # the reason of the layout change: removed virtual functions
10991 next if($VirtualReplacement{$VirtFunc});
10992 my $ProblemType = "Removed_Virtual_Method";
10993 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10994 $ProblemType = "Removed_Pure_Virtual_Method";
10995 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010996 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010997 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010998 "Target"=>get_Signature($VirtFunc, 1) );
10999 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011000 }
11001 }
11002 }
11003 }
11004 }
11005 }
11006 }
11007}
11008
11009sub isCreatable($$)
11010{
11011 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011012 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011013 or isCopyingClass($ClassId, $LibVersion)) {
11014 return 1;
11015 }
11016 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11017 { # Fix for incomplete data: if this class has
11018 # a base class then it should also has a constructor
11019 return 1;
11020 }
11021 if($ReturnedClass{$LibVersion}{$ClassId})
11022 { # returned by some method of this class
11023 # or any other class
11024 return 1;
11025 }
11026 return 0;
11027}
11028
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011029sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011030{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011031 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011032 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11033 { # parameter of some exported method
11034 return 1;
11035 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011036 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11037 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011038 { # method from target class
11039 return 1;
11040 }
11041 return 0;
11042}
11043
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011044sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011045{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011046 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011047 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011048 # - virtual
11049 # - pure-virtual
11050 # - non-virtual
11051 if($CompleteSignature{1}{$Interface}{"Data"})
11052 { # global data is not affected
11053 return;
11054 }
11055 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011056 if(not $Class_Id) {
11057 return;
11058 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011059 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011060 if(cmpVTables_Real($CName, 1)==0)
11061 { # no changes
11062 return;
11063 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011064 $CheckedTypes{$Level}{$CName} = 1;
11065 if($Level eq "Binary")
11066 { # Binary-level
11067 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11068 and not isUsedClass($Class_Id, 1, $Level))
11069 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011070 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011071 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011072 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011073 }
11074 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11075 {
11076 if(defined $VirtualTable{2}{$CName}{$Func}
11077 and defined $CompleteSignature{2}{$Func})
11078 {
11079 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11080 and $CompleteSignature{2}{$Func}{"PureVirt"})
11081 { # became pure virtual
11082 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11083 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011084 "Target"=>get_Signature_M($Func, 1) );
11085 $VTableChanged_M{$CName} = 1;
11086 }
11087 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11088 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11089 { # became non-pure virtual
11090 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_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 }
11096 }
11097 if($Level eq "Binary")
11098 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011099 # check virtual table structure
11100 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11101 {
11102 next if($Interface eq $AddedVFunc);
11103 next if($VirtualReplacement{$AddedVFunc});
11104 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11105 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11106 { # pure virtual methods affect all others (virtual and non-virtual)
11107 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011108 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011109 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011110 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011111 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011112 elsif(not defined $VirtualTable{1}{$CName}
11113 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011114 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011115 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011116 { # became polymorphous class, added v-table pointer
11117 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011118 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011119 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011120 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011121 }
11122 else
11123 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011124 my $VSize_Old = getVTable_Size($CName, 1);
11125 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011126 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011127 if(isCopyingClass($Class_Id, 1))
11128 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11129 my $ProblemType = "Added_Virtual_Method";
11130 if(isLeafClass($Class_Id, 1)) {
11131 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11132 }
11133 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11134 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011135 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011136 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011137 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011138 else
11139 {
11140 my $ProblemType = "Added_Virtual_Method";
11141 if(isLeafClass($Class_Id, 1)) {
11142 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11143 }
11144 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11145 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011146 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011147 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011148 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011149 }
11150 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011151 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11152 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011153 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011154 if(defined $VirtualTable{1}{$CName}
11155 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011156 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011157 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11158 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011159
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011160 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011161 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011162 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11163 foreach my $ASymbol (@Affected)
11164 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011165 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11166 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011167 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011168 next;
11169 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011170 }
11171 $CheckedSymbols{$Level}{$ASymbol} = 1;
11172 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11173 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011174 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011175 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011176 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011177 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011178 }
11179 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011180 else {
11181 # safe
11182 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011183 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011184 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11185 {
11186 next if($VirtualReplacement{$RemovedVFunc});
11187 if($RemovedVFunc eq $Interface
11188 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11189 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011190 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011191 next;
11192 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011193 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011194 { # became non-polymorphous class, removed v-table pointer
11195 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11196 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011197 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011198 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011199 }
11200 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11201 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11202 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011203 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011204 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011205 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11206 next;
11207 }
11208 my $VPos_New = -1;
11209 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011210 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011211 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11212 }
11213 else
11214 {
11215 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011216 next;
11217 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011218 }
11219 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11220 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11221 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11222 {
11223 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11224 foreach my $ASymbol (@Affected)
11225 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011226 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11227 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011228 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011229 next;
11230 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011231 }
11232 my $ProblemType = "Removed_Virtual_Method";
11233 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11234 $ProblemType = "Removed_Pure_Virtual_Method";
11235 }
11236 $CheckedSymbols{$Level}{$ASymbol} = 1;
11237 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11238 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011239 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011240 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011241 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011242 }
11243 }
11244 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011245 }
11246 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011247 else
11248 { # Source-level
11249 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011250 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011251 next if($Interface eq $AddedVFunc);
11252 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011253 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011254 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11255 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011256 "Target"=>get_Signature($AddedVFunc, 2) );
11257 }
11258 }
11259 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11260 {
11261 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11262 {
11263 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11264 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011265 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011266 }
11267 }
11268 }
11269}
11270
11271sub find_MemberPair_Pos_byName($$)
11272{
11273 my ($Member_Name, $Pair_Type) = @_;
11274 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11275 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11276 {
11277 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11278 {
11279 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11280 $Name=~s/\A[_]+|[_]+\Z//g;
11281 if($Name eq $Member_Name) {
11282 return $MemberPair_Pos;
11283 }
11284 }
11285 }
11286 return "lost";
11287}
11288
11289sub find_MemberPair_Pos_byVal($$)
11290{
11291 my ($Member_Value, $Pair_Type) = @_;
11292 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11293 {
11294 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11295 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11296 return $MemberPair_Pos;
11297 }
11298 }
11299 return "lost";
11300}
11301
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011302my %Severity_Val=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011303 "High"=>3,
11304 "Medium"=>2,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011305 "Low"=>1,
11306 "Safe"=>-1
11307);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011308
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011309sub maxSeverity($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011310{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011311 my ($S1, $S2) = @_;
11312 if(cmpSeverities($S1, $S2)) {
11313 return $S1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011314 }
11315 else {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011316 return $S2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011317 }
11318}
11319
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011320sub cmpSeverities($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011321{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011322 my ($S1, $S2) = @_;
11323 if(not $S1) {
11324 return 0;
11325 }
11326 elsif(not $S2) {
11327 return 1;
11328 }
11329 return ($Severity_Val{$S1}>$Severity_Val{$S2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011330}
11331
11332sub getProblemSeverity($$)
11333{
11334 my ($Level, $Kind) = @_;
11335 return $CompatRules{$Level}{$Kind}{"Severity"};
11336}
11337
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011338sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011339{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011340 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011341 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011342 if( $_->{"T1"} eq $_[0]
11343 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011344 {
11345 return 1;
11346 }
11347 }
11348 return 0;
11349}
11350
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011351sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011352{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011353 my %IDs = (
11354 "T1" => $_[0],
11355 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011356 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011357 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011358}
11359
11360sub isRenamed($$$$$)
11361{
11362 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11363 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11364 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011365 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011366 if(not defined $Type2->{"Memb"}{$MemPos}) {
11367 return "";
11368 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011369 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011370 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011371
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011372 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11373 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011374 if($MemberPair_Pos_Rev eq "lost")
11375 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011376 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11377 { # base type match
11378 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011379 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011380 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11381 { # exact type match
11382 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011383 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011384 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11385 { # size match
11386 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011387 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011388 if(isReserved($Pair_Name))
11389 { # reserved fields
11390 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011391 }
11392 }
11393 return "";
11394}
11395
11396sub isLastElem($$)
11397{
11398 my ($Pos, $TypeRef) = @_;
11399 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11400 if($Name=~/last|count|max|total/i)
11401 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11402 return 1;
11403 }
11404 elsif($Name=~/END|NLIMITS\Z/)
11405 { # __RLIMIT_NLIMITS
11406 return 1;
11407 }
11408 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11409 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11410 { # NImageFormats, NColorRoles
11411 return 1;
11412 }
11413 return 0;
11414}
11415
11416sub nonComparable($$)
11417{
11418 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011419
11420 my $N1 = $T1->{"Name"};
11421 my $N2 = $T2->{"Name"};
11422
11423 $N1=~s/\A(struct|union|enum) //;
11424 $N2=~s/\A(struct|union|enum) //;
11425
11426 if($N1 ne $N2
11427 and not isAnon($N1)
11428 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011429 { # different names
11430 if($T1->{"Type"} ne "Pointer"
11431 or $T2->{"Type"} ne "Pointer")
11432 { # compare base types
11433 return 1;
11434 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011435 if($N1!~/\Avoid\s*\*/
11436 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011437 {
11438 return 1;
11439 }
11440 }
11441 elsif($T1->{"Type"} ne $T2->{"Type"})
11442 { # different types
11443 if($T1->{"Type"} eq "Class"
11444 and $T2->{"Type"} eq "Struct")
11445 { # "class" to "struct"
11446 return 0;
11447 }
11448 elsif($T2->{"Type"} eq "Class"
11449 and $T1->{"Type"} eq "Struct")
11450 { # "struct" to "class"
11451 return 0;
11452 }
11453 else
11454 { # "class" to "enum"
11455 # "union" to "class"
11456 # ...
11457 return 1;
11458 }
11459 }
11460 return 0;
11461}
11462
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011463sub isOpaque($)
11464{
11465 my $T = $_[0];
11466 if(not defined $T->{"Memb"})
11467 {
11468 return 1;
11469 }
11470 return 0;
11471}
11472
11473sub removeVPtr($)
11474{ # support for old ABI dumps
11475 my $TPtr = $_[0];
11476 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11477 if($#Pos>=1)
11478 {
11479 foreach my $Pos (0 .. $#Pos-1)
11480 {
11481 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11482 }
11483 delete($TPtr->{"Memb"}{$#Pos});
11484 }
11485}
11486
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011487sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011488{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011489 my ($Type1_Id, $Type2_Id, $Level) = @_;
11490 return () if(not $Type1_Id or not $Type2_Id);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011491 my (%Sub_SubProblems, %SubProblems) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011492 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011493 { # already merged
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011494 return %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011495 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011496 my %Type1 = get_Type($Type1_Id, 1);
11497 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011498 if(not $Type1{"Name"} or not $Type2{"Name"}) {
11499 return ();
11500 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011501
11502 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011503 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11504 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011505 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11506
11507 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11508 {
11509 if($Type1_Pure{"Type"}=~/Struct|Union/
11510 and $Type2_Pure{"Type"}=~/Struct|Union/)
11511 {
11512 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11513 {
11514 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11515 "Target"=>$Type1_Pure{"Name"},
11516 "Type_Name"=>$Type1_Pure{"Name"} );
11517
11518 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
11519 return %SubProblems;
11520 }
11521 }
11522 }
11523
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011524 if(not $Type1_Pure{"Size"}
11525 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011526 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011527 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11528 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11529 { # NOTE: template instances have no size
11530 return ();
11531 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011532 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011533 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011534 { # skip recursive declarations
11535 return ();
11536 }
11537 return () if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11538 return () if($SkipTypes{1}{$Type1_Pure{"Name"}});
11539 return () if($SkipTypes{1}{$Type1{"Name"}});
11540
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011541 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11542 { # support for old ABI dumps
11543 # _vptr field added in 3.0
11544 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11545 {
11546 if(defined $Type2_Pure{"Memb"}
11547 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11548 {
11549 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11550 delete($Type2_Pure{"Memb"}{0});
11551 }
11552 else {
11553 removeVPtr(\%Type2_Pure);
11554 }
11555 }
11556 }
11557 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11558 {
11559 if(defined $Type1_Pure{"Memb"}
11560 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11561 {
11562 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11563 delete($Type1_Pure{"Memb"}{0});
11564 }
11565 else {
11566 removeVPtr(\%Type1_Pure);
11567 }
11568 }
11569 }
11570 }
11571
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011572 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11573 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011574
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011575 if(not $UseOldDumps and %Typedef_1 and %Typedef_2
11576 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11577 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011578 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011579 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11580 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011581 if($Base_1{"Name"} ne $Base_2{"Name"})
11582 {
11583 if(differentDumps("G")
11584 or differentDumps("V"))
11585 { # different GCC versions or different dumps
11586 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11587 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11588 # std::__va_list and __va_list
11589 $Base_1{"Name"}=~s/\A(\w+::)+//;
11590 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011591 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11592 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011593 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011594 }
11595 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11596 and $Base_1{"Name"} ne $Base_2{"Name"})
11597 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011598 if($Level eq "Binary"
11599 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011600 {
11601 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11602 "Target"=>$Typedef_1{"Name"},
11603 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011604 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11605 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11606 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011607 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11608 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011609 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011610 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011611 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11612 {
11613 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11614 "Target"=>$Typedef_1{"Name"},
11615 "Type_Name"=>$Typedef_1{"Name"},
11616 "Old_Value"=>$Base_1{"Name"},
11617 "New_Value"=>$Base_2{"Name"} );
11618 }
11619 else
11620 {
11621 %{$SubProblems{"Typedef_BaseType"}{$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 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011627 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011628 }
11629 }
11630 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11631 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011632 my $TT1 = $Type1_Pure{"Type"};
11633 my $TT2 = $Type2_Pure{"Type"};
11634
11635 if($TT1 ne $TT2
11636 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011637 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011638 my $Short1 = $Type1_Pure{"Name"};
11639 my $Short2 = $Type2_Pure{"Name"};
11640
11641 $Short1=~s/\A\Q$TT1\E //ig;
11642 $Short2=~s/\A\Q$TT2\E //ig;
11643
11644 if($Short1 eq $Short2)
11645 {
11646 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11647 "Target"=>$Type1_Pure{"Name"},
11648 "Type_Name"=>$Type1_Pure{"Name"},
11649 "Old_Value"=>lc($Type1_Pure{"Type"}),
11650 "New_Value"=>lc($Type2_Pure{"Type"}) );
11651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011652 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011653 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011654 return %SubProblems;
11655 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011656 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011657 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11658 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11659 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11660 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011661 if($Level eq "Binary"
11662 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011663 {
11664 my $ProblemKind = "DataType_Size";
11665 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011666 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011667 {
11668 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11669 $ProblemKind = "Size_Of_Copying_Class";
11670 }
11671 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11672 {
11673 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11674 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11675 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011676 else
11677 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011678 # descreased size of allocable class
11679 # it has no special effects
11680 }
11681 }
11682 }
11683 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11684 "Target"=>$Type1_Pure{"Name"},
11685 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011686 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
11687 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE,
11688 "InitialType_Type"=>$Type1_Pure{"Type"} );
11689 }
11690 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011691 if(defined $Type1_Pure{"BaseType"}
11692 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011693 { # checking base types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011694 %Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011695 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
11696 {
11697 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
11698 {
11699 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) {
11700 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr};
11701 }
11702 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{"InitialType_Type"} = $Type1_Pure{"Type"};
11703 }
11704 }
11705 }
11706 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11707 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11708 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11709 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11710 { # detect removed and renamed fields
11711 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11712 next if(not $Member_Name);
11713 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);
11714 if($MemberPair_Pos eq "lost")
11715 {
11716 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11717 {
11718 if(isUnnamed($Member_Name))
11719 { # support for old-version dumps
11720 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011721 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011722 next;
11723 }
11724 }
11725 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11726 { # renamed
11727 $RenamedField{$Member_Pos}=$RenamedTo;
11728 $RenamedField_Rev{$NameToPosB{$RenamedTo}}=$Member_Name;
11729 }
11730 else
11731 { # removed
11732 $RemovedField{$Member_Pos}=1;
11733 }
11734 }
11735 elsif($Type1_Pure{"Type"} eq "Enum")
11736 {
11737 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11738 next if($Member_Value1 eq "");
11739 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11740 if($MemberPair_Pos ne "lost")
11741 { # renamed
11742 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11743 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11744 if($MemberPair_Pos_Rev eq "lost")
11745 {
11746 $RenamedField{$Member_Pos}=$RenamedTo;
11747 $RenamedField_Rev{$NameToPosB{$RenamedTo}}=$Member_Name;
11748 }
11749 else {
11750 $RemovedField{$Member_Pos}=1;
11751 }
11752 }
11753 else
11754 { # removed
11755 $RemovedField{$Member_Pos}=1;
11756 }
11757 }
11758 }
11759 else
11760 { # related
11761 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11762 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11763 }
11764 }
11765 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11766 { # detect added fields
11767 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11768 next if(not $Member_Name);
11769 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);
11770 if($MemberPair_Pos eq "lost")
11771 {
11772 if(isUnnamed($Member_Name))
11773 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011774 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011775 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011776 next;
11777 }
11778 }
11779 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11780 {
11781 if(not $RenamedField_Rev{$Member_Pos})
11782 { # added
11783 $AddedField{$Member_Pos}=1;
11784 }
11785 }
11786 }
11787 }
11788 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11789 { # detect moved fields
11790 my (%RelPos, %RelPosName, %AbsPos) = ();
11791 my $Pos = 0;
11792 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11793 { # relative positions in 1st version
11794 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11795 next if(not $Member_Name);
11796 if(not $RemovedField{$Member_Pos})
11797 { # old type without removed fields
11798 $RelPos{1}{$Member_Name}=$Pos;
11799 $RelPosName{1}{$Pos} = $Member_Name;
11800 $AbsPos{1}{$Pos++} = $Member_Pos;
11801 }
11802 }
11803 $Pos = 0;
11804 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11805 { # relative positions in 2nd version
11806 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11807 next if(not $Member_Name);
11808 if(not $AddedField{$Member_Pos})
11809 { # new type without added fields
11810 $RelPos{2}{$Member_Name}=$Pos;
11811 $RelPosName{2}{$Pos} = $Member_Name;
11812 $AbsPos{2}{$Pos++} = $Member_Pos;
11813 }
11814 }
11815 foreach my $Member_Name (keys(%{$RelPos{1}}))
11816 {
11817 my $RPos1 = $RelPos{1}{$Member_Name};
11818 my $AbsPos1 = $NameToPosA{$Member_Name};
11819 my $Member_Name2 = $Member_Name;
11820 if(my $RenamedTo = $RenamedField{$AbsPos1})
11821 { # renamed
11822 $Member_Name2 = $RenamedTo;
11823 }
11824 my $RPos2 = $RelPos{2}{$Member_Name2};
11825 if($RPos2 ne "" and $RPos1 ne $RPos2)
11826 { # different relative positions
11827 my $AbsPos2 = $NameToPosB{$Member_Name2};
11828 if($AbsPos1 ne $AbsPos2)
11829 { # different absolute positions
11830 my $ProblemType = "Moved_Field";
11831 if(not isPublic(\%Type1_Pure, $AbsPos1))
11832 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011833 if($Level eq "Source") {
11834 next;
11835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011836 $ProblemType = "Moved_Private_Field";
11837 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011838 if($Level eq "Binary"
11839 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011840 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011841 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011842 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011843 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011844 if($MemSize1 ne $MemSize2) {
11845 $ProblemType .= "_And_Size";
11846 }
11847 }
11848 if($ProblemType eq "Moved_Private_Field") {
11849 next;
11850 }
11851 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11852 "Target"=>$Member_Name,
11853 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011854 "Old_Value"=>$RPos1,
11855 "New_Value"=>$RPos2 );
11856 }
11857 }
11858 }
11859 }
11860 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011861 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011862 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11863 next if(not $Member_Name);
11864 if(my $RenamedTo = $RenamedField{$Member_Pos})
11865 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011866 if(defined $Constants{2}{$Member_Name})
11867 {
11868 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11869 { # define OLD NEW
11870 next; # Safe
11871 }
11872 }
11873
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011874 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11875 {
11876 if(isPublic(\%Type1_Pure, $Member_Pos))
11877 {
11878 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11879 "Target"=>$Member_Name,
11880 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011881 "Old_Value"=>$Member_Name,
11882 "New_Value"=>$RenamedTo );
11883 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011884 elsif(isReserved($Member_Name))
11885 {
11886 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11887 "Target"=>$Member_Name,
11888 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011889 "Old_Value"=>$Member_Name,
11890 "New_Value"=>$RenamedTo );
11891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011892 }
11893 elsif($Type1_Pure{"Type"} eq "Enum")
11894 {
11895 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11896 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11897 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011898 "Old_Value"=>$Member_Name,
11899 "New_Value"=>$RenamedTo );
11900 }
11901 }
11902 elsif($RemovedField{$Member_Pos})
11903 { # removed
11904 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11905 {
11906 my $ProblemType = "Removed_Field";
11907 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011908 or isUnnamed($Member_Name))
11909 {
11910 if($Level eq "Source") {
11911 next;
11912 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011913 $ProblemType = "Removed_Private_Field";
11914 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011915 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011916 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011917 {
11918 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11919 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011920 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 +040011921 { # changed offset
11922 $ProblemType .= "_And_Layout";
11923 }
11924 }
11925 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11926 { # affected size
11927 $ProblemType .= "_And_Size";
11928 }
11929 }
11930 if($ProblemType eq "Removed_Private_Field") {
11931 next;
11932 }
11933 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11934 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011935 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011936 }
11937 elsif($Type2_Pure{"Type"} eq "Union")
11938 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011939 if($Level eq "Binary"
11940 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011941 {
11942 %{$SubProblems{"Removed_Union_Field_And_Size"}{$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 else
11947 {
11948 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11949 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011950 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011951 }
11952 }
11953 elsif($Type1_Pure{"Type"} eq "Enum")
11954 {
11955 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11956 "Target"=>$Member_Name,
11957 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011958 "Old_Value"=>$Member_Name );
11959 }
11960 }
11961 else
11962 { # changed
11963 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11964 if($Type1_Pure{"Type"} eq "Enum")
11965 {
11966 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11967 next if($Member_Value1 eq "");
11968 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11969 next if($Member_Value2 eq "");
11970 if($Member_Value1 ne $Member_Value2)
11971 {
11972 my $ProblemType = "Enum_Member_Value";
11973 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11974 $ProblemType = "Enum_Last_Member_Value";
11975 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011976 if($SkipConstants{1}{$Member_Name}) {
11977 $ProblemType = "Enum_Private_Member_Value";
11978 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011979 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11980 "Target"=>$Member_Name,
11981 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011982 "Old_Value"=>$Member_Value1,
11983 "New_Value"=>$Member_Value2 );
11984 }
11985 }
11986 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11987 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011988 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11989 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11990
11991 if($Access1 ne "private"
11992 and $Access2 eq "private")
11993 {
11994 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11995 "Target"=>$Member_Name,
11996 "Type_Name"=>$Type1_Pure{"Name"});
11997 }
11998 elsif($Access1 ne "protected"
11999 and $Access1 ne "private"
12000 and $Access2 eq "protected")
12001 {
12002 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12003 "Target"=>$Member_Name,
12004 "Type_Name"=>$Type1_Pure{"Name"});
12005 }
12006
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012007 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12008 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012009 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012010 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12011 $SizeV1 = $BSize1;
12012 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012013 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012014 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12015 $SizeV2 = $BSize2;
12016 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012017 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12018 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012019 if($Level eq "Binary"
12020 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012021 {
12022 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12023 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12024 { # field size change (including anon-structures and unions)
12025 # - same types
12026 # - unnamed types
12027 # - bitfields
12028 my $ProblemType = "Field_Size";
12029 if(not isPublic(\%Type1_Pure, $Member_Pos)
12030 or isUnnamed($Member_Name))
12031 { # should not be accessed by applications, goes to "Low Severity"
12032 # example: "abidata" members in GStreamer types
12033 $ProblemType = "Private_".$ProblemType;
12034 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012035 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 +040012036 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012037 if($Type2_Pure{"Type"} ne "Union"
12038 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012039 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012040 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 +040012041 { # changed offset
12042 $ProblemType .= "_And_Layout";
12043 }
12044 }
12045 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12046 $ProblemType .= "_And_Type_Size";
12047 }
12048 }
12049 if($ProblemType eq "Private_Field_Size")
12050 { # private field size with no effect
12051 $ProblemType = "";
12052 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012053 if($ProblemType eq "Field_Size")
12054 {
12055 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12056 { # Low severity
12057 $ProblemType = "Struct_Field_Size_Increased";
12058 }
12059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012060 if($ProblemType)
12061 { # register a problem
12062 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12063 "Target"=>$Member_Name,
12064 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012065 "Old_Size"=>$SizeV1,
12066 "New_Size"=>$SizeV2);
12067 }
12068 }
12069 }
12070 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12071 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12072 { # do NOT check bitfield type changes
12073 next;
12074 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012075 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012076 {
12077 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12078 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12079 {
12080 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12081 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012082 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012083 }
12084 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12085 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12086 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012087 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012088 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012089 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012090 }
12091 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012092 %Sub_SubProblems = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012093 foreach my $ProblemType (keys(%Sub_SubProblems))
12094 {
12095 my $Old_Value = $Sub_SubProblems{$ProblemType}{"Old_Value"};
12096 my $New_Value = $Sub_SubProblems{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012097
12098 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012099 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012100 or $ProblemType eq "Field_Type_And_Size"
12101 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012102 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012103 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012104 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012105 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012106 %{$Sub_SubProblems{"Field_Became_Volatile"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012107 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012108 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
12109 %{$Sub_SubProblems{"Field_Became_Non_Volatile"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012110 }
12111 }
12112 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12113 {
12114 if($RA==2) {
12115 %{$Sub_SubProblems{"Field_Added_Const"}} = %{$Sub_SubProblems{$ProblemType}};
12116 }
12117 else {
12118 %{$Sub_SubProblems{"Field_Became_Const"}} = %{$Sub_SubProblems{$ProblemType}};
12119 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012120 }
12121 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12122 {
12123 if($RR==2) {
12124 %{$Sub_SubProblems{"Field_Removed_Const"}} = %{$Sub_SubProblems{$ProblemType}};
12125 }
12126 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012127 %{$Sub_SubProblems{"Field_Became_Non_Const"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012128 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012129 }
12130 }
12131 }
12132
12133 if($Level eq "Source")
12134 {
12135 foreach my $ProblemType (keys(%Sub_SubProblems))
12136 {
12137 my $Old_Value = $Sub_SubProblems{$ProblemType}{"Old_Value"};
12138 my $New_Value = $Sub_SubProblems{$ProblemType}{"New_Value"};
12139
12140 if($ProblemType eq "Field_Type")
12141 {
12142 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012143 delete($Sub_SubProblems{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012144 }
12145 }
12146 }
12147 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012148
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012149 foreach my $ProblemType (keys(%Sub_SubProblems))
12150 {
12151 my $ProblemType_Init = $ProblemType;
12152 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012153 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012154 if(not isPublic(\%Type1_Pure, $Member_Pos)
12155 or isUnnamed($Member_Name)) {
12156 $ProblemType = "Private_".$ProblemType;
12157 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012158 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 +040012159 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012160 if($Type2_Pure{"Type"} ne "Union"
12161 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012162 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012163 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 +040012164 { # changed offset
12165 $ProblemType .= "_And_Layout";
12166 }
12167 }
12168 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12169 $ProblemType .= "_And_Type_Size";
12170 }
12171 }
12172 }
12173 else
12174 {
12175 if(not isPublic(\%Type1_Pure, $Member_Pos)
12176 or isUnnamed($Member_Name)) {
12177 next;
12178 }
12179 }
12180 if($ProblemType eq "Private_Field_Type_And_Size")
12181 { # private field change with no effect
12182 next;
12183 }
12184 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12185 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012186 "Type_Name"=>$Type1_Pure{"Name"});
12187
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012188 foreach my $Attr (keys(%{$Sub_SubProblems{$ProblemType_Init}}))
12189 { # other properties
12190 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubProblems{$ProblemType_Init}{$Attr};
12191 }
12192 }
12193 if(not isPublic(\%Type1_Pure, $Member_Pos))
12194 { # do NOT check internal type changes
12195 next;
12196 }
12197 if($MemberType1_Id and $MemberType2_Id)
12198 {# checking member type changes (replace)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012199 %Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012200 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
12201 {
12202 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
12203 {
12204 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12205 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"IsInTypeInternals"}=1;
12206 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) {
12207 $SubProblems{$Sub_SubProblemType}{$NewLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr};
12208 }
12209 if($Sub_SubLocation!~/\-\>/) {
12210 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"Start_Type_Name"} = $MemberType1_Name;
12211 }
12212 }
12213 }
12214 }
12215 }
12216 }
12217 }
12218 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12219 { # checking added members, public and private
12220 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12221 next if(not $Member_Name);
12222 if($AddedField{$Member_Pos})
12223 { # added
12224 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12225 {
12226 my $ProblemType = "Added_Field";
12227 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012228 or isUnnamed($Member_Name))
12229 {
12230 if($Level eq "Source") {
12231 next;
12232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012233 $ProblemType = "Added_Private_Field";
12234 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012235 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012236 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012237 {
12238 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12239 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012240 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 +040012241 { # changed offset
12242 $ProblemType .= "_And_Layout";
12243 }
12244 }
12245 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12246 $ProblemType .= "_And_Size";
12247 }
12248 }
12249 if($ProblemType eq "Added_Private_Field")
12250 { # skip added private fields
12251 next;
12252 }
12253 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12254 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012255 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012256 }
12257 elsif($Type2_Pure{"Type"} eq "Union")
12258 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012259 if($Level eq "Binary"
12260 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012261 {
12262 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12263 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012264 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012265 }
12266 else
12267 {
12268 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12269 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012270 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012271 }
12272 }
12273 elsif($Type2_Pure{"Type"} eq "Enum")
12274 {
12275 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12276 next if($Member_Value eq "");
12277 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12278 "Target"=>$Member_Name,
12279 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012280 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012281 }
12282 }
12283 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012284 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012285 pop(@RecurTypes);
12286 return %SubProblems;
12287}
12288
12289sub isUnnamed($) {
12290 return $_[0]=~/\Aunnamed\d+\Z/;
12291}
12292
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012293sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012294{
12295 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012296 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12297 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12298 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12299 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012300 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012301 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012302 }
12303 return $TypeName;
12304}
12305
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012306sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012307{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012308 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012309 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012310 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12311 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012312 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012313 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12314 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012315 return () if(not $Type{"Type"});
12316 if($Type{"Type"} ne $Type_Type)
12317 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012318 return () if(not $Type{"BaseType"});
12319 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012320 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012321 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012322 return %Type;
12323}
12324
12325my %TypeSpecAttributes = (
12326 "Const" => 1,
12327 "Volatile" => 1,
12328 "ConstVolatile" => 1,
12329 "Restrict" => 1,
12330 "Typedef" => 1
12331);
12332
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012333sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012334{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012335 my ($TypeId, $Info) = @_;
12336 if(not $TypeId or not $Info
12337 or not $Info->{$TypeId}) {
12338 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012339 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012340 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12341 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12342 }
12343 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012344 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012345 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012346 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012347 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012348 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012349 return %Type;
12350}
12351
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012352sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012353{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012354 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012355 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012356 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12357 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012358 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012359 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12360 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012361 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12362 my $PLevel = 0;
12363 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12364 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012365 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012366 return $PLevel if(not $Type{"BaseType"});
12367 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12368 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12369 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012370}
12371
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012372sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012373{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012374 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012375 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012376 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12377 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012378 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012379 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12380 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012381 return %Type if(not $Type{"BaseType"});
12382 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012383 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012384 return %Type;
12385}
12386
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012387sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012388{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012389 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012390 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012391 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12392 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012393 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012394 my $Qual = "";
12395 if($Type{"Type"} eq "Pointer") {
12396 $Qual .= "*";
12397 }
12398 elsif($Type{"Type"} eq "Ref") {
12399 $Qual .= "&";
12400 }
12401 elsif($Type{"Type"} eq "ConstVolatile") {
12402 $Qual .= "const volatile";
12403 }
12404 elsif($Type{"Type"} eq "Const"
12405 or $Type{"Type"} eq "Volatile"
12406 or $Type{"Type"} eq "Restrict") {
12407 $Qual .= lc($Type{"Type"});
12408 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012409 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012410 return $BQual.$Qual;
12411}
12412
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012413sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012414{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012415 my ($TypeId, $Info) = @_;
12416 if(not $TypeId or not $Info
12417 or not $Info->{$TypeId}) {
12418 return ();
12419 }
12420 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012421 return %Type if(not $Type{"BaseType"});
12422 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012423 {
12424 if($Info->{$BTid}) {
12425 return %{$Info->{$BTid}};
12426 }
12427 else { # something is going wrong
12428 return ();
12429 }
12430 }
12431 else {
12432 return %Type;
12433 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012434}
12435
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012436sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012437{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012438 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012439 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012440 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12441 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012442}
12443
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012444sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012445{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012446 my $Symbol = $_[0];
12447 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12448}
12449
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012450sub isInLineInst($$$) {
12451 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12452}
12453
12454sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012455{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012456 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012457 if($CheckObjectsOnly)
12458 {
12459 if($Symbol!~/\A(_Z|\?)/) {
12460 return 0;
12461 }
12462 if(my $Signature = $tr_name{$Symbol})
12463 {
12464 if(index($Signature,">")==-1) {
12465 return 0;
12466 }
12467 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
12468 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012469 if(index($ShortName,"<")!=-1
12470 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012471 return 1;
12472 }
12473 }
12474 }
12475 }
12476 else
12477 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012478 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012479 {
12480 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
12481 {
12482 if(index($ClassName,"<")!=-1) {
12483 return 1;
12484 }
12485 }
12486 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012487 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012488 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012489 if(index($ShortName,"<")!=-1
12490 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012491 return 1;
12492 }
12493 }
12494 }
12495 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012496}
12497
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012498sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012499{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012500 my ($Symbol, $SInfo, $LibVersion) = @_;
12501 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012502 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012503 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012504 { # class specialization
12505 return 1;
12506 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012507 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012508 { # method specialization
12509 return 1;
12510 }
12511 }
12512 return 0;
12513}
12514
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012515sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012516{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012517 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012518 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012519 { # non-public global data
12520 return 0;
12521 }
12522 if($CheckObjectsOnly) {
12523 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
12524 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012525 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012526 { # support for old ABI dumps in --headers-only mode
12527 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12528 {
12529 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12530 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012531 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012532 if(not $PType or $PType eq "Unknown") {
12533 return 0;
12534 }
12535 }
12536 }
12537 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012538 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012539 {
12540 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012541 if($SkipSymbols{$LibVersion}{$Symbol})
12542 { # user defined symbols to ignore
12543 return 0;
12544 }
12545 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12546 if(not $NameSpace and $ClassId)
12547 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012548 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012549 }
12550 if($NameSpace)
12551 { # user defined namespaces to ignore
12552 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12553 return 0;
12554 }
12555 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12556 { # nested namespaces
12557 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12558 return 0;
12559 }
12560 }
12561 }
12562 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
12563 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012564 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012565 { # --skip-headers or <skip_headers> (not <skip_including>)
12566 if($Skip==1) {
12567 return 0;
12568 }
12569 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012570 }
12571 if($SymbolsListPath and not $SymbolsList{$Symbol})
12572 { # user defined symbols
12573 return 0;
12574 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012575 if($SkipSymbolsListPath and $SkipSymbolsList{$Symbol})
12576 { # user defined symbols
12577 return 0;
12578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012579 if($AppPath and not $SymbolsList_App{$Symbol})
12580 { # user defined symbols (in application)
12581 return 0;
12582 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012583 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12584 { # non-target symbols
12585 return 0;
12586 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012587 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012588 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012589 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012590 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012591 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012592 return 0;
12593 }
12594 }
12595 else
12596 {
12597 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012598 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012599 {
12600 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12601 { # inline virtual methods
12602 if($Type=~/InlineVirt/) {
12603 return 1;
12604 }
12605 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12606 if(not $Allocable)
12607 { # check bases
12608 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12609 {
12610 if(not isCopyingClass($DCId, $LibVersion))
12611 { # exists a derived class without default c-tor
12612 $Allocable=1;
12613 last;
12614 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012616 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012617 if(not $Allocable) {
12618 return 0;
12619 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012620 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012621 else
12622 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012623 return 0;
12624 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012625 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012626 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012627 }
12628 }
12629 return 1;
12630}
12631
12632sub mergeImpl()
12633{
12634 my $DiffCmd = get_CmdPath("diff");
12635 if(not $DiffCmd) {
12636 exitStatus("Not_Found", "can't find \"diff\"");
12637 }
12638 foreach my $Interface (sort keys(%{$Symbol_Library{1}}))
12639 { # implementation changes
12640 next if($CompleteSignature{1}{$Interface}{"Private"});
12641 next if(not $CompleteSignature{1}{$Interface}{"Header"} and not $CheckObjectsOnly);
12642 next if(not $Symbol_Library{2}{$Interface} and not $Symbol_Library{2}{$SymVer{2}{$Interface}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012643 if(not symbolFilter($Interface, 1, "Affected", "Binary")) {
12644 next;
12645 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012646 my $Impl1 = canonifyImpl($Interface_Impl{1}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012647 next if(not $Impl1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012648 my $Impl2 = canonifyImpl($Interface_Impl{2}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012649 next if(not $Impl2);
12650 if($Impl1 ne $Impl2)
12651 {
12652 writeFile("$TMP_DIR/impl1", $Impl1);
12653 writeFile("$TMP_DIR/impl2", $Impl2);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012654 my $Diff = `$DiffCmd -rNau \"$TMP_DIR/impl1\" \"$TMP_DIR/impl2\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012655 $Diff=~s/(---|\+\+\+).+\n//g;
12656 $Diff=~s/[ ]{3,}/ /g;
12657 $Diff=~s/\n\@\@/\n \n\@\@/g;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012658 unlink("$TMP_DIR/impl1");
12659 unlink("$TMP_DIR/impl2");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040012660 %{$CompatProblems_Impl{$Interface}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012661 "Diff" => get_CodeView($Diff) );
12662 }
12663 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012664
12665 # clean memory
12666 %Interface_Impl = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012667}
12668
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012669sub canonifyImpl($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012670{
12671 my $FuncBody= $_[0];
12672 return "" if(not $FuncBody);
12673 $FuncBody=~s/0x[a-f\d]+/0x?/g;# addr
12674 $FuncBody=~s/((\A|\n)[a-z]+[\t ]+)[a-f\d]+([^x]|\Z)/$1?$3/g;# call, jump
12675 $FuncBody=~s/# [a-f\d]+ /# ? /g;# call, jump
12676 $FuncBody=~s/%([a-z]+[a-f\d]*)/\%reg/g;# registers
12677 while($FuncBody=~s/\nnop[ \t]*(\n|\Z)/$1/g){};# empty op
12678 $FuncBody=~s/<.+?\.cpp.+?>/<name.cpp>/g;
12679 $FuncBody=~s/(\A|\n)[a-f\d]+ </$1? </g;# 5e74 <_ZN...
12680 $FuncBody=~s/\.L\d+/.L/g;
12681 $FuncBody=~s/#(-?)\d+/#$1?/g;# r3, [r3, #120]
12682 $FuncBody=~s/[\n]{2,}/\n/g;
12683 return $FuncBody;
12684}
12685
12686sub get_CodeView($)
12687{
12688 my $Code = $_[0];
12689 my $View = "";
12690 foreach my $Line (split(/\n/, $Code))
12691 {
12692 if($Line=~s/\A(\+|-)/$1 /g)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012693 { # bold line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012694 $View .= "<tr><td><b>".htmlSpecChars($Line)."</b></td></tr>\n";
12695 }
12696 else {
12697 $View .= "<tr><td>".htmlSpecChars($Line)."</td></tr>\n";
12698 }
12699 }
12700 return "<table class='code_view'>$View</table>\n";
12701}
12702
12703sub getImplementations($$)
12704{
12705 my ($LibVersion, $Path) = @_;
12706 return if(not $LibVersion or not -e $Path);
12707 if($OSgroup eq "macos")
12708 {
12709 my $OtoolCmd = get_CmdPath("otool");
12710 if(not $OtoolCmd) {
12711 exitStatus("Not_Found", "can't find \"otool\"");
12712 }
12713 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012714 foreach my $Line (split(/\n/, `$OtoolCmd -tv \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012715 {
12716 if($Line=~/\A\s*_(\w+)\s*:/i) {
12717 $CurInterface = $1;
12718 }
12719 elsif($Line=~/\A\s*[\da-z]+\s+(.+?)\Z/i) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012720 $Interface_Impl{$LibVersion}{$CurInterface} .= $1."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012721 }
12722 }
12723 }
12724 else
12725 {
12726 my $ObjdumpCmd = get_CmdPath("objdump");
12727 if(not $ObjdumpCmd) {
12728 exitStatus("Not_Found", "can't find \"objdump\"");
12729 }
12730 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012731 foreach my $Line (split(/\n/, `$ObjdumpCmd -d \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012732 {
12733 if($Line=~/\A[\da-z]+\s+<(\w+)>/i) {
12734 $CurInterface = $1;
12735 }
12736 else
12737 { # x86: 51fa:(\t)89 e5 (\t)mov %esp,%ebp
12738 # arm: 5020:(\t)e24cb004(\t)sub(\t)fp, ip, #4(\t); 0x4
12739 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 +040012740 $Interface_Impl{$LibVersion}{$CurInterface} .= $2."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012741 }
12742 }
12743 }
12744 }
12745}
12746
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012747sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012748{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012749 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012750 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12751 {
12752 if(link_symbol($Symbol, 1, "+Deps"))
12753 { # linker can find a new symbol
12754 # in the old-version library
12755 # So, it's not a new symbol
12756 next;
12757 }
12758 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012759 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012760 next;
12761 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012762 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012763 }
12764}
12765
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012766sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012767{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012768 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012769 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12770 {
12771 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012772 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012773 }
12774 if(link_symbol($Symbol, 2, "+Deps"))
12775 { # linker can find an old symbol
12776 # in the new-version library
12777 next;
12778 }
12779 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012780 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012781 next;
12782 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012783 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012784 }
12785}
12786
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012787sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012788{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012789 my $Level = $_[0];
12790 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012791 { # checking added symbols
12792 next if($CompleteSignature{2}{$Symbol}{"Private"});
12793 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012794 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012795 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012796 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012797 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012798 { # checking removed symbols
12799 next if($CompleteSignature{1}{$Symbol}{"Private"});
12800 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012801 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012802 { # skip v-tables for templates, that should not be imported by applications
12803 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012804 if(my $CName = $VTableClass{$Symbol})
12805 {
12806 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12807 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012808 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012809 next;
12810 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012811 }
12812 }
12813 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012814 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012815 }
12816 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12817 { # symbols for pure virtual methods cannot be called by clients
12818 next;
12819 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012820 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012821 }
12822}
12823
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012824sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012825{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012826 my ($LibVersion, $V) = @_;
12827 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12828 return $Cache{"checkDump"}{$LibVersion}{$V};
12829 }
12830 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012831}
12832
12833sub detectAdded_H($)
12834{
12835 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012836 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12837 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012838 if($Level eq "Source")
12839 { # remove symbol version
12840 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12841 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012842
12843 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12844 { # skip artificial constructors
12845 next;
12846 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012847 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012848 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12849 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012850 next;
12851 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012852 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012853 next;
12854 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012855 if(not defined $CompleteSignature{1}{$Symbol}
12856 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12857 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012858 if($UsedDump{2}{"SrcBin"})
12859 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012860 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012861 { # support for old and different (!) ABI dumps
12862 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12863 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012864 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012865 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012866 {
12867 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12868 {
12869 if($Lang eq "C")
12870 { # support for old ABI dumps: missed extern "C" functions
12871 next;
12872 }
12873 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012874 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012875 else
12876 {
12877 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012878 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012879 next;
12880 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012881 }
12882 }
12883 }
12884 }
12885 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012886 }
12887 }
12888}
12889
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012890sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012891{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012892 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012893 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12894 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012895 if($Level eq "Source")
12896 { # remove symbol version
12897 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12898 $Symbol=$SN;
12899 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012900 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12901 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012902 next;
12903 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012904 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012905 next;
12906 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012907 if(not defined $CompleteSignature{2}{$Symbol}
12908 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012909 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012910 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012911 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012912 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012913 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012914 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12915 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012916 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012917 if($CheckHeadersOnly)
12918 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012919 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12920 {
12921 if($Lang eq "C")
12922 { # support for old ABI dumps: missed extern "C" functions
12923 next;
12924 }
12925 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012926 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012927 else
12928 {
12929 if(not link_symbol($Symbol, 1, "-Deps"))
12930 { # skip removed inline symbols
12931 next;
12932 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012933 }
12934 }
12935 }
12936 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012937 if(not checkDump(1, "2.15"))
12938 {
12939 if($Symbol=~/_IT_E\Z/)
12940 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12941 next;
12942 }
12943 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012944 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12945 {
12946 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12947 {
12948 if(defined $Constants{2}{$Short})
12949 {
12950 my $Val = $Constants{2}{$Short}{"Value"};
12951 if(defined $Func_ShortName{2}{$Val})
12952 { # old name defined to new
12953 next;
12954 }
12955 }
12956 }
12957
12958 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012959 $RemovedInt{$Level}{$Symbol} = 1;
12960 if($Level eq "Source")
12961 { # search for a source-compatible equivalent
12962 setAlternative($Symbol, $Level);
12963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012964 }
12965 }
12966}
12967
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012968sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012969{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012970 my $Level = $_[0];
12971 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012972 { # checking added symbols
12973 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012974 next if($CompleteSignature{2}{$Symbol}{"Private"});
12975 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012976 if($Level eq "Binary")
12977 {
12978 if($CompleteSignature{2}{$Symbol}{"InLine"})
12979 {
12980 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12981 { # skip inline non-virtual functions
12982 next;
12983 }
12984 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012985 }
12986 else
12987 { # Source
12988 if($SourceAlternative_B{$Symbol}) {
12989 next;
12990 }
12991 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012992 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012993 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012994 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012995 { # checking removed symbols
12996 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012997 next if($CompleteSignature{1}{$Symbol}{"Private"});
12998 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012999 if($Level eq "Binary")
13000 {
13001 if($CompleteSignature{1}{$Symbol}{"InLine"})
13002 {
13003 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13004 { # skip inline non-virtual functions
13005 next;
13006 }
13007 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013008 }
13009 else
13010 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013011 if(my $Alt = $SourceAlternative{$Symbol})
13012 {
13013 if(defined $CompleteSignature{1}{$Alt}
13014 and $CompleteSignature{1}{$Symbol}{"Const"})
13015 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013016 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013017 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013018 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013019 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013020 }
13021 else
13022 { # do NOT show removed symbol
13023 next;
13024 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013025 }
13026 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013027 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013028 }
13029}
13030
13031sub addParamNames($)
13032{
13033 my $LibraryVersion = $_[0];
13034 return if(not keys(%AddIntParams));
13035 my $SecondVersion = $LibraryVersion==1?2:1;
13036 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13037 {
13038 next if(not keys(%{$AddIntParams{$Interface}}));
13039 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013040 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013041 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13042 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013043 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013044 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13045 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13046 {
13047 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13048 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13049 }
13050 }
13051 else {
13052 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13053 }
13054 }
13055 }
13056 }
13057}
13058
13059sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013060{ # detect changed typedefs to show
13061 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013062 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13063 {
13064 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013065 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13066 if(not $BName1 or isAnon($BName1)) {
13067 next;
13068 }
13069 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13070 if(not $BName2 or isAnon($BName2)) {
13071 next;
13072 }
13073 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013074 $ChangedTypedef{$Typedef} = 1;
13075 }
13076 }
13077}
13078
13079sub get_symbol_suffix($$)
13080{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013081 my ($Symbol, $Full) = @_;
13082 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013083 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013084 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013085 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013086 if(not $Full) {
13087 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13088 }
13089 return $Suffix;
13090}
13091
13092sub get_symbol_prefix($$)
13093{
13094 my ($Symbol, $LibVersion) = @_;
13095 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13096 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13097 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013098 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013099 }
13100 return $ShortName;
13101}
13102
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013103sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013104{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013105 my $Symbol = $_[0];
13106 my $PSymbol = $Symbol;
13107 if(not defined $CompleteSignature{2}{$PSymbol}
13108 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13109 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13110 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013111 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013112 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013113 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013114 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013115 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13116 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013117 {
13118 if(defined $CompleteSignature{2}{$PSymbol}
13119 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13120 {
13121 $SourceAlternative{$Symbol} = $PSymbol;
13122 $SourceAlternative_B{$PSymbol} = $Symbol;
13123 if(not defined $CompleteSignature{1}{$PSymbol}
13124 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13125 $SourceReplacement{$Symbol} = $PSymbol;
13126 }
13127 }
13128 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013129 }
13130 else
13131 {
13132 foreach my $Sp ("KV", "VK", "K", "V")
13133 {
13134 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13135 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13136 {
13137 if(defined $CompleteSignature{2}{$PSymbol}
13138 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13139 {
13140 $SourceAlternative{$Symbol} = $PSymbol;
13141 $SourceAlternative_B{$PSymbol} = $Symbol;
13142 if(not defined $CompleteSignature{1}{$PSymbol}
13143 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13144 $SourceReplacement{$Symbol} = $PSymbol;
13145 }
13146 }
13147 }
13148 $PSymbol = $Symbol;
13149 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013150 }
13151 }
13152 }
13153 return "";
13154}
13155
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013156sub getSymKind($$)
13157{
13158 my ($Symbol, $LibVersion) = @_;
13159 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13160 {
13161 return "Global_Data";
13162 }
13163 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13164 {
13165 return "Method";
13166 }
13167 return "Function";
13168}
13169
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013170sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013171{
13172 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013173 my %SubProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013174
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013175 mergeBases($Level);
13176
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013177 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013178 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013179 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013180 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013181 next;
13182 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013183 if(defined $CompleteSignature{1}{$Symbol}
13184 and $CompleteSignature{1}{$Symbol}{"Header"})
13185 { # double-check added symbol
13186 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013187 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013188 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013189 next;
13190 }
13191 if($Symbol=~/\A(_Z|\?)/)
13192 { # C++
13193 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13194 }
13195 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13196 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013197 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13198 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013199 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013200 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013201 {
13202 if($TName_Tid{1}{$AffectedClass_Name})
13203 { # class should exist in previous version
13204 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13205 { # old v-table is NOT copied by old applications
13206 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13207 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013208 "Target"=>get_Signature($Symbol, 2),
13209 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013210 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013211 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013213 }
13214 }
13215 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013216 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13217 { # check all removed exported symbols
13218 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013219 next;
13220 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013221 if(defined $CompleteSignature{2}{$Symbol}
13222 and $CompleteSignature{2}{$Symbol}{"Header"})
13223 { # double-check removed symbol
13224 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013225 }
13226 if($CompleteSignature{1}{$Symbol}{"Private"})
13227 { # skip private methods
13228 next;
13229 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013230 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013231 next;
13232 }
13233 $CheckedSymbols{$Level}{$Symbol} = 1;
13234 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13235 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013236 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13237 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013238 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013239 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13240 {
13241 if($TName_Tid{2}{$AffectedClass_Name})
13242 { # class should exist in newer version
13243 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13244 { # old v-table is NOT copied by old applications
13245 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13246 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013247 "Target"=>get_Signature($OverriddenMethod, 1),
13248 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013249 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013250 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013252 }
13253 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013254 if($Level eq "Binary"
13255 and $OSgroup eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013256 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013257 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013258 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013259 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013260 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013261 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013262 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013263 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013264 {
13265 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13266 "Target"=>$tr_name{$Symbol},
13267 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013268 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013269 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013270 else
13271 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013272 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013273 "Target"=>$tr_name{$Symbol},
13274 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013275 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013276 }
13277 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013278 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013279 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013280 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013281 {
13282 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13283 "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 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013287 else
13288 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013289 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013290 "Target"=>$tr_name{$Symbol},
13291 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013292 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013293 }
13294 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013295 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13296 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13297 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13298 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13299 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013300 {
13301 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013302 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013303 $ProblemType = "Global_Data_Symbol_Changed_Type";
13304 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013305 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13306 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013307 "Old_Type"=>$RTName1,
13308 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013309 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013310 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013311 }
13312 }
13313 }
13314 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013315 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013316 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013317 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013318 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013319 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013320 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013321 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013322 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13323 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013324 if($Symbol=~/(C1E|C2E)/)
13325 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013326 my $CtorType = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013327 $NewSym=~s/(C1E|C2E)/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013328 }
13329 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013330 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13331 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013332 if($Symbol=~/(D0E|D1E|D2E)/)
13333 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013334 my $DtorType = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013335 $NewSym=~s/(D0E|D1E|D2E)/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013336 }
13337 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013338 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013339 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013340 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013341 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013342 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013343 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013344 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013345 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013346 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013347 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013348 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013349 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013350 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013351 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013352 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013353 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013354 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013355 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013356 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013357 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013358 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013359 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013360 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013361 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013362 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013363 { # "volatile" to non-"volatile"
13364
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013365 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013366 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013367 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013368 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013369 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013370 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013371 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013372 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013373 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013374 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013375 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013376 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013377 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013378 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013379 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013380 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013381 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013382 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13383 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013384 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013385 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013386 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013387 }
13388 }
13389 }
13390 }
13391 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013392 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13393 { # checking symbols
13394 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13395 if($Level eq "Source")
13396 { # remove symbol version
13397 $Symbol=$SN;
13398 }
13399 else
13400 { # Binary
13401 if(not $SV)
13402 { # symbol without version
13403 if(my $VSym = $SymVer{1}{$Symbol})
13404 { # the symbol is linked with versioned symbol
13405 if($CompleteSignature{2}{$VSym}{"MnglName"})
13406 { # show report for symbol@ver only
13407 next;
13408 }
13409 elsif(not link_symbol($VSym, 2, "-Deps"))
13410 { # changed version: sym@v1 to sym@v2
13411 # do NOT show report for symbol
13412 next;
13413 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013414 }
13415 }
13416 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013417 my $PSymbol = $Symbol;
13418 if($Level eq "Source"
13419 and my $S = $SourceReplacement{$Symbol})
13420 { # take a source-compatible replacement function
13421 $PSymbol = $S;
13422 }
13423 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013424 { # private symbols
13425 next;
13426 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013427 if(not defined $CompleteSignature{1}{$Symbol}
13428 or not defined $CompleteSignature{2}{$PSymbol})
13429 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013430 next;
13431 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013432 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13433 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13434 { # no mangled name
13435 next;
13436 }
13437 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13438 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013439 { # without a header
13440 next;
13441 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013442
13443 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13444 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13445 { # became pure
13446 next;
13447 }
13448 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13449 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13450 { # became non-pure
13451 next;
13452 }
13453
13454 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13455 { # exported, target, inline virtual and pure virtual
13456 next;
13457 }
13458 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13459 { # exported, target, inline virtual and pure virtual
13460 next;
13461 }
13462
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013463 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013464 {
13465 if($CompleteSignature{1}{$Symbol}{"Data"}
13466 and $CompleteSignature{2}{$PSymbol}{"Data"})
13467 {
13468 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13469 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13470 if(defined $Value1)
13471 {
13472 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13473 if(defined $Value2)
13474 {
13475 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13476 if($Value1 ne $Value2)
13477 {
13478 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13479 "Old_Value"=>$Value1,
13480 "New_Value"=>$Value2,
13481 "Target"=>get_Signature($Symbol, 1) );
13482 }
13483 }
13484 }
13485 }
13486 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013487
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013488 if($CompleteSignature{2}{$PSymbol}{"Private"})
13489 {
13490 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13491 "Target"=>get_Signature_M($PSymbol, 2) );
13492 }
13493 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13494 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13495 {
13496 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13497 "Target"=>get_Signature_M($PSymbol, 2) );
13498 }
13499 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13500 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13501 {
13502 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13503 "Target"=>get_Signature_M($PSymbol, 2) );
13504 }
13505
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013506 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013507 mergeVirtualTables($Symbol, $Level);
13508
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013509 if($COMPILE_ERRORS)
13510 { # if some errors occurred at the compiling stage
13511 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013512 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013513 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013514 { # missed information about parameters in newer version
13515 next;
13516 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013517 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013518 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013519 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013520 next;
13521 }
13522 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013523 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013524 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013525 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013526 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13527 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013528 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13529 "Target"=>get_Signature($Symbol, 1)
13530 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013531 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013532 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013533 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13534 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013535 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013536 "Target"=>get_Signature($Symbol, 1)
13537 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013538 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013539 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13540 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013541 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013542 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013543 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013544 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13545 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13546 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013547 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013548 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013549 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13550 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013551 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013552 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013553 my $ProblemType = "Virtual_Method_Position";
13554 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13555 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013556 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013557 if(isUsedClass($Class_Id, 1, $Level))
13558 {
13559 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013560 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013561 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013562 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13563 next;
13564 }
13565 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013566 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013567 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13568 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013569 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013570 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013571 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013572 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013573 }
13574 }
13575 }
13576 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013577 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13578 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013579 { # do NOT check type changes in pure virtuals
13580 next;
13581 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013582 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013583 if($Symbol=~/\A(_Z|\?)/
13584 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013585 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013586 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013587 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013588 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013589 }
13590 }
13591 else
13592 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013593 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013594 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013595 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013596 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13597 last if($PType2_Name eq "...");
13598 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13599 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013600 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013601 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013602 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013603 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13604 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013605 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13606 $ParamPos_Prev = "lost";
13607 }
13608 }
13609 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013610 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013611 }
13612 if($ParamPos_Prev eq "lost")
13613 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013614 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013615 {
13616 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013617 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013618 $ProblemType = "Added_Unnamed_Parameter";
13619 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013620 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013621 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013622 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013623 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013624 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013625 }
13626 else
13627 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013628 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013629 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013630 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013631 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13632 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013633 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013634 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013635 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013636 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013637 "Target"=>$PName_Old,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013638 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013639 "Param_Type"=>$PType2_Name,
13640 "Old_Value"=>$PName_Old,
13641 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013642 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013643 }
13644 }
13645 else
13646 {
13647 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013648 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013649 $ProblemType = "Added_Middle_Unnamed_Parameter";
13650 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013651 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013652 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013653 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013654 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013655 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013656 }
13657 }
13658 }
13659 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013660 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013661 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013662 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013663 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013664 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013665 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013666 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013667 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013668 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013669 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13670 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013671 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013672 }
13673 }
13674 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013675 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013676 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013677 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013678 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13679 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013680 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13681 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013682 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013683 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013684 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013685 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13686 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013687 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13688 $ParamPos_New = "lost";
13689 }
13690 }
13691 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013692 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013693 }
13694 if($ParamPos_New eq "lost")
13695 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013696 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013697 {
13698 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013699 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013700 $ProblemType = "Removed_Unnamed_Parameter";
13701 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013702 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013703 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013704 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013705 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013706 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013707 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013708 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013709 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013710 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013711 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013712 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013713 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013714 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013715 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013716 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013717 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013718 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013719 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013720 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013721 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013722 "Old_Value"=>$PName,
13723 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013724 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013725 }
13726 }
13727 else
13728 {
13729 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013730 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013731 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13732 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013733 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013734 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013735 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013736 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013737 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013738 }
13739 }
13740 }
13741 }
13742 }
13743 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013744 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13745 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
13746 %SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013747
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013748 foreach my $SubProblemType (keys(%SubProblems))
13749 {
13750 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13751 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013752 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013753
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013754 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013755 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013756 if($SubProblemType eq "Return_Type_And_Size") {
13757 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13758 }
13759 elsif($SubProblemType eq "Return_Type_Format") {
13760 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13761 }
13762 else {
13763 $ProblemTypes{"Global_Data_Type"} = 1;
13764 }
13765
13766 # quals
13767 if($SubProblemType eq "Return_Type"
13768 or $SubProblemType eq "Return_Type_And_Size"
13769 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013770 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013771 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13772 { # const to non-const
13773 if($RR==2) {
13774 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13775 }
13776 else {
13777 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13778 }
13779 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013780 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013781 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13782 { # non-const to const
13783 if($RA==2) {
13784 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13785 }
13786 else {
13787 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13788 }
13789 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013790 }
13791 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013792 }
13793 else
13794 {
13795 # quals
13796 if($SubProblemType eq "Return_Type"
13797 or $SubProblemType eq "Return_Type_And_Size"
13798 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013799 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013800 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013801 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013802 if(addedQual($Old_Value, $New_Value, "volatile"))
13803 {
13804 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13805 if($Level ne "Source"
13806 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13807 $ProblemTypes{"Return_Type"} = 1;
13808 }
13809 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013810 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013811 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13812 {
13813 if($RA==2) {
13814 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13815 }
13816 else {
13817 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13818 }
13819 if($Level ne "Source"
13820 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13821 $ProblemTypes{"Return_Type"} = 1;
13822 }
13823 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013824 }
13825 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013826 if($Level eq "Binary"
13827 and not $CompleteSignature{1}{$Symbol}{"Data"})
13828 {
13829 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13830 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13831 { # if one of the architectures is unknown
13832 # then set other arhitecture to unknown too
13833 ($Arch1, $Arch2) = ("unknown", "unknown");
13834 }
13835 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013836 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013837 {
13838 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13839 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13840 }
13841 else
13842 {
13843 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13844 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13845 }
13846
13847 if($SubProblemType eq "Return_Type_Became_Void")
13848 {
13849 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13850 { # parameters stack has been affected
13851 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013852 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013853 }
13854 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013855 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013856 }
13857 }
13858 }
13859 elsif($SubProblemType eq "Return_Type_From_Void")
13860 {
13861 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13862 { # parameters stack has been affected
13863 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013864 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013865 }
13866 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013867 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013868 }
13869 }
13870 }
13871 elsif($SubProblemType eq "Return_Type"
13872 or $SubProblemType eq "Return_Type_And_Size"
13873 or $SubProblemType eq "Return_Type_Format")
13874 {
13875 if($Conv1{"Method"} ne $Conv2{"Method"})
13876 {
13877 if($Conv1{"Method"} eq "stack")
13878 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013879 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013880 }
13881 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013882 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013883 }
13884 }
13885 else
13886 {
13887 if($Conv1{"Method"} eq "reg")
13888 {
13889 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13890 {
13891 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013892 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013893 }
13894 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013895 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013896 }
13897 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013898 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013899 }
13900 }
13901 }
13902 }
13903 }
13904 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013905
13906 if(not keys(%ProblemTypes))
13907 { # default
13908 $ProblemTypes{$SubProblemType} = 1;
13909 }
13910
13911 foreach my $ProblemType (keys(%ProblemTypes))
13912 { # additional
13913 @{$CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013914 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013915 }
13916 if($ReturnType1_Id and $ReturnType2_Id)
13917 {
13918 @RecurTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013919 %SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013920
13921 if($CompleteSignature{1}{$Symbol}{"Data"})
13922 {
13923 if($Level eq "Binary")
13924 {
13925 if(get_PLevel($ReturnType1_Id, 1)==0)
13926 {
13927 foreach my $SubProblemType (keys(%SubProblems))
13928 { # add "Global_Data_Size" problem
13929 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13930 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
13931 if($SubProblemType eq "DataType_Size")
13932 { # add a new problem
13933 %{$SubProblems{"Global_Data_Size"}} = %{$SubProblems{$SubProblemType}};
13934 }
13935 }
13936 }
13937 if(not defined $SubProblems{"Global_Data_Size"})
13938 {
13939 if(defined $GlobalDataObject{1}{$Symbol}
13940 and defined $GlobalDataObject{2}{$Symbol})
13941 {
13942 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13943 my $New_Size = $GlobalDataObject{2}{$Symbol};
13944 if($Old_Size!=$New_Size)
13945 {
13946 %{$SubProblems{"Global_Data_Size"}{"retval"}} = (
13947 "Old_Size"=>$Old_Size*$BYTE_SIZE,
13948 "New_Size"=>$New_Size*$BYTE_SIZE );
13949 }
13950 }
13951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013952 }
13953 }
13954 foreach my $SubProblemType (keys(%SubProblems))
13955 {
13956 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
13957 {
13958 my $NewLocation = ($SubLocation)?"retval->".$SubLocation:"retval";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013959 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013960 "Return_Type_Name"=>$TypeInfo{1}{$ReturnType1_Id}{"Name"} );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013961 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013962 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013963 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ReturnType1_Id}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013964 }
13965 }
13966 }
13967 }
13968
13969 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013970 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13971 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13972 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013973 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013974 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013975 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13976 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013977 if($ThisPtr1_Id and $ThisPtr2_Id)
13978 {
13979 @RecurTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013980 %SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013981 foreach my $SubProblemType (keys(%SubProblems))
13982 {
13983 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
13984 {
13985 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013986 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013987 "Object_Type_Name"=>$TypeInfo{1}{$ObjTId1}{"Name"} );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013988 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013989 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013990 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ObjTId1}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013991 }
13992 }
13993 }
13994 }
13995 }
13996 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013997 if($Level eq "Binary") {
13998 mergeVTables($Level);
13999 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014000 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14001 $CheckedSymbols{$Level}{$Symbol} = 1;
14002 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014003}
14004
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014005sub rmQuals($$)
14006{
14007 my ($Value, $Qual) = @_;
14008 if(not $Qual) {
14009 return $Value;
14010 }
14011 if($Qual eq "all")
14012 { # all quals
14013 $Qual = "const|volatile|restrict";
14014 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014015 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014016 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014017 }
14018 return $Value;
14019}
14020
14021sub cmpBTypes($$$$)
14022{
14023 my ($T1, $T2, $V1, $V2) = @_;
14024 $T1 = uncover_typedefs($T1, $V1);
14025 $T2 = uncover_typedefs($T2, $V2);
14026 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14027}
14028
14029sub addedQual($$$)
14030{
14031 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014032 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014033}
14034
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014035sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014036{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014037 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014038 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014039}
14040
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014041sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014042{
14043 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14044 $Old_Value = uncover_typedefs($Old_Value, $V1);
14045 $New_Value = uncover_typedefs($New_Value, $V2);
14046 if($Old_Value eq $New_Value)
14047 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014048 return 0;
14049 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014050 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014051 { # without a qual
14052 return 0;
14053 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014054 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014055 { # became non-qual
14056 return 1;
14057 }
14058 else
14059 {
14060 my @BQ1 = getQualModel($Old_Value, $Qual);
14061 my @BQ2 = getQualModel($New_Value, $Qual);
14062 foreach (0 .. $#BQ1)
14063 { # removed qual
14064 if($BQ1[$_]==1
14065 and $BQ2[$_]!=1)
14066 {
14067 return 2;
14068 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014069 }
14070 }
14071 return 0;
14072}
14073
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014074sub getQualModel($$)
14075{
14076 my ($Value, $Qual) = @_;
14077 if(not $Qual) {
14078 return $Value;
14079 }
14080
14081 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014082 while($Value=~/(\w+)/ and $1 ne $Qual) {
14083 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014084 }
14085 $Value=~s/[^\*\&\w]+//g;
14086
14087 # modeling
14088 # int*const*const == 011
14089 # int**const == 001
14090 my @Model = ();
14091 my @Elems = split(/[\*\&]/, $Value);
14092 if(not @Elems) {
14093 return (0);
14094 }
14095 foreach (@Elems)
14096 {
14097 if($_ eq $Qual) {
14098 push(@Model, 1);
14099 }
14100 else {
14101 push(@Model, 0);
14102 }
14103 }
14104
14105 return @Model;
14106}
14107
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014108my %StringTypes = map {$_=>1} (
14109 "char*",
14110 "char const*"
14111);
14112
14113my %CharTypes = map {$_=>1} (
14114 "char",
14115 "char const"
14116);
14117
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014118sub showVal($$$)
14119{
14120 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014121 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014122 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014123 if(substr($Value, 0, 2) eq "_Z")
14124 {
14125 if(my $Unmangled = $tr_name{$Value}) {
14126 return $Unmangled;
14127 }
14128 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014129 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014130 { # strings
14131 return "\"$Value\"";
14132 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014133 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014134 { # characters
14135 return "\'$Value\'";
14136 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014137 if($Value eq "")
14138 { # other
14139 return "\'\'";
14140 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014141 return $Value;
14142}
14143
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014144sub getRegs($$$)
14145{
14146 my ($LibVersion, $Symbol, $Pos) = @_;
14147
14148 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14149 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014150 my %Regs = ();
14151 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14152 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014153 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014154 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14155 }
14156 }
14157
14158 return join(", ", sort keys(%Regs));
14159 }
14160
14161 return undef;
14162}
14163
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014164sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014165{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014166 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014167 if(not $Symbol) {
14168 return;
14169 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014170 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14171 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14172 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14173 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014174 if(not $PType1_Id
14175 or not $PType2_Id) {
14176 return;
14177 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014178
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014179 if(index($Symbol, "_Z")==0)
14180 { # do not merge "this"
14181 if($PName1 eq "this" or $PName2 eq "this") {
14182 return;
14183 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014184 }
14185
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014186 my %Type1 = get_Type($PType1_Id, 1);
14187 my %Type2 = get_Type($PType2_Id, 2);
14188 my %BaseType1 = get_BaseType($PType1_Id, 1);
14189 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014190 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014191
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014192 if($Level eq "Binary")
14193 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014194 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014195 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14196 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14197 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14198 {
14199 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014200 "Target"=>$PName1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014201 "Param_Pos"=>$ParamPos1 );
14202 }
14203 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14204 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14205 {
14206 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014207 "Target"=>$PName1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014208 "Param_Pos"=>$ParamPos1 );
14209 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014210 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014211
14212 if(defined $UsedDump{1}{"DWARF"}
14213 and defined $UsedDump{2}{"DWARF"})
14214 {
14215 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14216 {
14217 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14218 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14219 if($Old_Regs and $New_Regs)
14220 {
14221 if($Old_Regs ne $New_Regs)
14222 {
14223 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14224 "Target"=>$PName1,
14225 "Param_Pos"=>$ParamPos1,
14226 "Old_Value"=>$Old_Regs,
14227 "New_Value"=>$New_Regs );
14228 }
14229 }
14230 elsif($Old_Regs and not $New_Regs)
14231 {
14232 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14233 "Target"=>$PName1,
14234 "Param_Pos"=>$ParamPos1,
14235 "Old_Value"=>$Old_Regs );
14236 }
14237 elsif(not $Old_Regs and $New_Regs)
14238 {
14239 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14240 "Target"=>$PName1,
14241 "Param_Pos"=>$ParamPos1,
14242 "New_Value"=>$New_Regs );
14243 }
14244 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14245 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14246 {
14247 if($Old_Offset ne $New_Offset)
14248 {
14249 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14250 "Target"=>$PName1,
14251 "Param_Pos"=>$ParamPos1,
14252 "Old_Value"=>$Old_Offset,
14253 "New_Value"=>$New_Offset );
14254 }
14255 }
14256 }
14257 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014258 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014259 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14260 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014261 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014262 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014263 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14264 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014265 if(not checkDump(1, "2.13")
14266 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014267 { # support for old ABI dumps
14268 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014269 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014270 if($Type1{"Name"} eq "bool"
14271 and $Value_Old eq "false" and $Value_New eq "0")
14272 { # int class::method ( bool p = 0 );
14273 # old ABI dumps: "false"
14274 # new ABI dumps: "0"
14275 $Value_Old = "0";
14276 }
14277 }
14278 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014279 if(not checkDump(1, "2.18")
14280 and checkDump(2, "2.18"))
14281 { # support for old ABI dumps
14282 if(not defined $Value_Old
14283 and substr($Value_New, 0, 2) eq "_Z") {
14284 $Value_Old = $Value_New;
14285 }
14286 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014287 if(defined $Value_Old)
14288 {
14289 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14290 if(defined $Value_New)
14291 {
14292 $Value_New = showVal($Value_New, $PType2_Id, 2);
14293 if($Value_Old ne $Value_New)
14294 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014295 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014296 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014297 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014298 "Old_Value"=>$Value_Old,
14299 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014300 }
14301 }
14302 else
14303 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014304 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014305 "Target"=>$PName1,
14306 "Param_Pos"=>$ParamPos1,
14307 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014308 }
14309 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014310 elsif(defined $Value_New)
14311 {
14312 $Value_New = showVal($Value_New, $PType2_Id, 2);
14313 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14314 "Target"=>$PName1,
14315 "Param_Pos"=>$ParamPos1,
14316 "New_Value"=>$Value_New );
14317 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014318 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014319
14320 if($ChkRnmd)
14321 {
14322 if($PName1 and $PName2 and $PName1 ne $PName2
14323 and $PType1_Id!=-1 and $PType2_Id!=-1
14324 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14325 { # except unnamed "..." value list (Id=-1)
14326 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14327 "Target"=>$PName1,
14328 "Param_Pos"=>$ParamPos1,
14329 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14330 "Old_Value"=>$PName1,
14331 "New_Value"=>$PName2,
14332 "New_Signature"=>get_Signature($Symbol, 2) );
14333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014334 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014335
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014336 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014337 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014338 foreach my $SubProblemType (keys(%SubProblems))
14339 { # add new problems, remove false alarms
14340 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14341 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014342
14343 # quals
14344 if($SubProblemType eq "Parameter_Type"
14345 or $SubProblemType eq "Parameter_Type_And_Size"
14346 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014347 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014348 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014349 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014350 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014351 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014352 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014353 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14354 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14355 }
14356 }
14357 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14358 {
14359 if(removedQual($Old_Value, $New_Value, "volatile")) {
14360 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014361 }
14362 }
14363 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14364 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14365 { # int to "int const"
14366 delete($SubProblems{$SubProblemType});
14367 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014368 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014369 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14370 { # "int const" to int
14371 delete($SubProblems{$SubProblemType});
14372 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014373 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14374 { # "const" to non-"const"
14375 if($RR==2) {
14376 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14377 }
14378 else {
14379 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14380 }
14381 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014382 }
14383 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014384
14385 if($Level eq "Source")
14386 {
14387 foreach my $SubProblemType (keys(%SubProblems))
14388 {
14389 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14390 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14391
14392 if($SubProblemType eq "Parameter_Type")
14393 {
14394 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14395 delete($SubProblems{$SubProblemType});
14396 }
14397 }
14398 }
14399 }
14400
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014401 foreach my $SubProblemType (keys(%SubProblems))
14402 { # modify/register problems
14403 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14404 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014405 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14406 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014407
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014408 my $NewProblemType = $SubProblemType;
14409 if($Old_Value eq "..." and $New_Value ne "...")
14410 { # change from "..." to "int"
14411 if($ParamPos1==0)
14412 { # ISO C requires a named argument before "..."
14413 next;
14414 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014415 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014416 }
14417 elsif($New_Value eq "..." and $Old_Value ne "...")
14418 { # change from "int" to "..."
14419 if($ParamPos2==0)
14420 { # ISO C requires a named argument before "..."
14421 next;
14422 }
14423 $NewProblemType = "Parameter_Became_VaList";
14424 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014425 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014426 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014427 {
14428 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014429 if($Arch1 eq "unknown"
14430 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014431 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014432 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014433 ($Arch1, $Arch2) = ("unknown", "unknown");
14434 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014435 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014436 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014437 { # real
14438 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14439 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14440 }
14441 else
14442 { # model
14443 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14444 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14445 }
14446 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014447 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014448 if($Conv1{"Method"} eq "stack")
14449 {
14450 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14451 $NewProblemType = "Parameter_Type_And_Stack";
14452 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014453 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014454 elsif($Conv1{"Method"} eq "reg")
14455 {
14456 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14457 $NewProblemType = "Parameter_Type_And_Register";
14458 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014459 }
14460 }
14461 else
14462 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014463 if($Conv1{"Method"} eq "stack") {
14464 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014465 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014466 elsif($Conv1{"Method"} eq "register") {
14467 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014468 }
14469 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014470 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14471 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014472 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014473 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014474 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014475 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014476 "New_Signature"=>get_Signature($Symbol, 2) );
14477 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014478 }
14479 @RecurTypes = ();
14480 # checking type definition changes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014481 my %SubProblems_Merge = mergeTypes($PType1_Id, $PType2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014482 foreach my $SubProblemType (keys(%SubProblems_Merge))
14483 {
14484 foreach my $SubLocation (keys(%{$SubProblems_Merge{$SubProblemType}}))
14485 {
14486 my $NewProblemType = $SubProblemType;
14487 if($SubProblemType eq "DataType_Size")
14488 {
14489 my $InitialType_Type = $SubProblems_Merge{$SubProblemType}{$SubLocation}{"InitialType_Type"};
14490 if($InitialType_Type!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
14491 { # stack has been affected
14492 $NewProblemType = "DataType_Size_And_Stack";
14493 }
14494 }
14495 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014496 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014497 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014498 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014499 "Param_Name"=>$PName1 );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014500 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}{keys(%{$SubProblems_Merge{$SubProblemType}{$SubLocation}})} = values %{$SubProblems_Merge{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014501 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014502 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$PType1_Id}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014503 }
14504 }
14505 }
14506}
14507
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014508sub find_ParamPair_Pos_byName($$$)
14509{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014510 my ($Name, $Symbol, $LibVersion) = @_;
14511 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014512 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014513 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14514 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014515 {
14516 return $ParamPos;
14517 }
14518 }
14519 return "lost";
14520}
14521
14522sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14523{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014524 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014525 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014526 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014527 {
14528 next if($Order eq "backward" and $ParamPos>$MediumPos);
14529 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014530 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14531 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014532 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014533 push(@Positions, $ParamPos);
14534 }
14535 }
14536 return @Positions;
14537}
14538
14539sub getTypeIdByName($$)
14540{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014541 my ($TypeName, $LibVersion) = @_;
14542 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014543}
14544
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014545sub diffTypes($$$)
14546{
14547 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14548 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14549 }
14550 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14551 { # skip recursive declarations
14552 return 0;
14553 }
14554
14555 pushType($_[0], $_[1], \@RecurTypes_Diff);
14556 my $Diff = diffTypes_I(@_);
14557 pop(@RecurTypes_Diff);
14558
14559 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14560}
14561
14562sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014563{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014564 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014565
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014566 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14567 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014568
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014569 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14570 { # equal types
14571 return 0;
14572 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014573 if($Type1_Pure{"Name"} eq "void")
14574 { # from void* to something
14575 return 0;
14576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014577 if($Type1_Pure{"Name"}=~/\*/
14578 or $Type2_Pure{"Name"}=~/\*/)
14579 { # compared in detectTypeChange()
14580 return 0;
14581 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014582
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014583 my %FloatType = map {$_=>1} (
14584 "float",
14585 "double",
14586 "long double"
14587 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014588
14589 my $T1 = $Type1_Pure{"Type"};
14590 my $T2 = $Type2_Pure{"Type"};
14591
14592 if($T1 eq "Struct"
14593 and $T2 eq "Class")
14594 { # compare as data structures
14595 $T2 = "Struct";
14596 }
14597
14598 if($T1 eq "Class"
14599 and $T2 eq "Struct")
14600 { # compare as data structures
14601 $T1 = "Struct";
14602 }
14603
14604 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014605 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014606 if($T1 eq "Intrinsic"
14607 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014608 { # "int" to "enum"
14609 return 0;
14610 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014611 elsif($T2 eq "Intrinsic"
14612 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014613 { # "enum" to "int"
14614 return 0;
14615 }
14616 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014617 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014618 # ...
14619 return 1;
14620 }
14621 }
14622 else
14623 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014624 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014625 {
14626 if($FloatType{$Type1_Pure{"Name"}}
14627 or $FloatType{$Type2_Pure{"Name"}})
14628 { # "float" to "double"
14629 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014630 if($Level eq "Source")
14631 { # Safe
14632 return 0;
14633 }
14634 else {
14635 return 1;
14636 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014637 }
14638 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014639 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014640 {
14641 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14642 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014643 if(not @Membs1
14644 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014645 { # private
14646 return 0;
14647 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014648 if($#Membs1!=$#Membs2)
14649 { # different number of elements
14650 return 1;
14651 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014652 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014653 {
14654 foreach my $Pos (@Membs1)
14655 { # compare elements by name and value
14656 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14657 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14658 { # different names
14659 return 1;
14660 }
14661 }
14662 }
14663 else
14664 {
14665 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014666 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014667 if($Level eq "Source")
14668 {
14669 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14670 { # different names
14671 return 1;
14672 }
14673 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014674
14675 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14676 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14677
14678 if($MT1{"Name"} ne $MT2{"Name"}
14679 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14680 {
14681 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14682 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14683
14684 if($PL1 ne $PL2)
14685 { # different pointer level
14686 return 1;
14687 }
14688
14689 # compare base types
14690 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14691 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14692
14693 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14694 { # different types
14695 return 1;
14696 }
14697 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014698 }
14699 }
14700 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014701 else
14702 {
14703 # TODO: arrays, etc.
14704 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014705 }
14706 return 0;
14707}
14708
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014709sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014710{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014711 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014712 if(not $Type1_Id or not $Type2_Id) {
14713 return ();
14714 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014715 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014716 my %Type1 = get_Type($Type1_Id, 1);
14717 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014718 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14719 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14720 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14721 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 +040014722
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014723 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14724 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014725 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14726 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14727 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14728 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14729 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14730 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14731 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014732 if($Type1{"Name"} eq $Type2{"Name"})
14733 {
14734 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14735 { # will be reported in mergeTypes() as typedef problem
14736 return ();
14737 }
14738 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14739 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14740 if(%Typedef_1 and %Typedef_2)
14741 {
14742 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14743 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14744 { # const Typedef
14745 return ();
14746 }
14747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014748 }
14749 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14750 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014751 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014752 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14753 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014754 {
14755 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14756 "Old_Value"=>$Type1_Base{"Name"},
14757 "New_Value"=>$Type2_Base{"Name"},
14758 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14759 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
14760 "InitialType_Type"=>$Type1_Pure{"Type"});
14761 }
14762 else
14763 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014764 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014765 { # format change
14766 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14767 "Old_Value"=>$Type1_Base{"Name"},
14768 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014769 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14770 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014771 "InitialType_Type"=>$Type1_Pure{"Type"});
14772 }
14773 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14774 {
14775 %{$LocalProblems{$Prefix."_BaseType"}}=(
14776 "Old_Value"=>$Type1_Base{"Name"},
14777 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014778 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14779 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014780 "InitialType_Type"=>$Type1_Pure{"Type"});
14781 }
14782 }
14783 }
14784 }
14785 elsif($Type1{"Name"} ne $Type2{"Name"})
14786 { # type change
14787 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14788 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014789 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014790 and $Type1_Pure{"Name"} eq "void")
14791 {
14792 %{$LocalProblems{"Return_Type_From_Void"}}=(
14793 "New_Value"=>$Type2{"Name"},
14794 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
14795 "InitialType_Type"=>$Type1_Pure{"Type"});
14796 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014797 elsif($Prefix eq "Return"
14798 and $Type2_Pure{"Name"} eq "void")
14799 {
14800 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14801 "Old_Value"=>$Type1{"Name"},
14802 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14803 "InitialType_Type"=>$Type1_Pure{"Type"});
14804 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014805 else
14806 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014807 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014808 and $Type1{"Size"} and $Type2{"Size"}
14809 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014810 {
14811 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14812 "Old_Value"=>$Type1{"Name"},
14813 "New_Value"=>$Type2{"Name"},
14814 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14815 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
14816 "InitialType_Type"=>$Type1_Pure{"Type"});
14817 }
14818 else
14819 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014820 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014821 { # format change
14822 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14823 "Old_Value"=>$Type1{"Name"},
14824 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014825 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14826 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014827 "InitialType_Type"=>$Type1_Pure{"Type"});
14828 }
14829 elsif(tNameLock($Type1_Id, $Type2_Id))
14830 { # FIXME: correct this condition
14831 %{$LocalProblems{$Prefix."_Type"}}=(
14832 "Old_Value"=>$Type1{"Name"},
14833 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014834 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14835 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014836 "InitialType_Type"=>$Type1_Pure{"Type"});
14837 }
14838 }
14839 }
14840 }
14841 }
14842 if($Type1_PLevel!=$Type2_PLevel)
14843 {
14844 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14845 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14846 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014847 if($Level eq "Source")
14848 {
14849 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014850 "Old_Value"=>$Type1_PLevel,
14851 "New_Value"=>$Type2_PLevel);
14852 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014853 else
14854 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014855 if($Type2_PLevel>$Type1_PLevel)
14856 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014857 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14858 "Old_Value"=>$Type1_PLevel,
14859 "New_Value"=>$Type2_PLevel);
14860 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014861 else
14862 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014863 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14864 "Old_Value"=>$Type1_PLevel,
14865 "New_Value"=>$Type2_PLevel);
14866 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014867 }
14868 }
14869 }
14870 if($Type1_Pure{"Type"} eq "Array")
14871 { # base_type[N] -> base_type[N]
14872 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014873 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014874 foreach my $SubProblemType (keys(%SubProblems))
14875 {
14876 $SubProblemType=~s/_Type/_BaseType/g;
14877 next if(defined $LocalProblems{$SubProblemType});
14878 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14879 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14880 }
14881 }
14882 }
14883 return %LocalProblems;
14884}
14885
14886sub tNameLock($$)
14887{
14888 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014889 my $Changed = 0;
14890 if(differentDumps("G"))
14891 { # different GCC versions
14892 $Changed = 1;
14893 }
14894 elsif(differentDumps("V"))
14895 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014896 if(not checkDump(1, "2.20")
14897 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014898 { # latest names update
14899 # 2.6: added restrict qualifier
14900 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014901 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014902 $Changed = 1;
14903 }
14904 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014905
14906 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14907 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14908
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014909 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014910 { # different formats
14911 if($UseOldDumps)
14912 { # old dumps
14913 return 0;
14914 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014915
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014916 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14917 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014918
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014919 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014920 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014921 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014922 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014923 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014924 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014925 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014926 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014927 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14928 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14929 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014930 { # equal base types
14931 return 0;
14932 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014933
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014934 if(not checkDump(1, "2.13")
14935 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014936 { # broken array names in ABI dumps < 2.13
14937 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014938 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014939 return 0;
14940 }
14941 }
14942
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014943 if(not checkDump(1, "2.6")
14944 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014945 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014946 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014947 and $TN2=~/\brestrict\b/) {
14948 return 0;
14949 }
14950 }
14951
14952 if(not checkDump(1, "2.20")
14953 or not checkDump(2, "2.20"))
14954 { # added restrict attribute in 2.6
14955 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14956 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014957 return 0;
14958 }
14959 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014960 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014961 else
14962 {
14963 # typedef struct {...} type_t
14964 # typedef struct type_t {...} type_t
14965 if(index($TN1, " ".$TN2)!=-1)
14966 {
14967 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14968 return 0;
14969 }
14970 }
14971 if(index($TN2, " ".$TN1)!=-1)
14972 {
14973 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14974 return 0;
14975 }
14976 }
14977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014978 return 1;
14979}
14980
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014981sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014982{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014983 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014984 if(defined $Cache{"differentDumps"}{$Check}) {
14985 return $Cache{"differentDumps"}{$Check};
14986 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014987 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014988 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014989 if($Check eq "G")
14990 {
14991 if(getGccVersion(1) ne getGccVersion(2))
14992 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014993 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014994 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014995 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014996 if($Check eq "V")
14997 {
14998 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14999 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15000 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015001 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015002 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015004 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015005 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015006}
15007
15008sub formatVersion($$)
15009{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015010 my ($V, $Digits) = @_;
15011 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015012 return join(".", splice(@Elems, 0, $Digits));
15013}
15014
15015sub htmlSpecChars($)
15016{
15017 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015018 if(not $Str) {
15019 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015020 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015021 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15022 $Str=~s/</&lt;/g;
15023 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15024 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015025 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15026 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015027 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015028 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015029 $Str=~s/\n/<br\/>/g;
15030 $Str=~s/\"/&quot;/g;
15031 $Str=~s/\'/&#39;/g;
15032 return $Str;
15033}
15034
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015035sub xmlSpecChars($)
15036{
15037 my $Str = $_[0];
15038 if(not $Str) {
15039 return $Str;
15040 }
15041
15042 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15043 $Str=~s/</&lt;/g;
15044 $Str=~s/>/&gt;/g;
15045
15046 $Str=~s/\"/&quot;/g;
15047 $Str=~s/\'/&#39;/g;
15048
15049 return $Str;
15050}
15051
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015052sub xmlSpecChars_R($)
15053{
15054 my $Str = $_[0];
15055 if(not $Str) {
15056 return $Str;
15057 }
15058
15059 $Str=~s/&amp;/&/g;
15060 $Str=~s/&lt;/</g;
15061 $Str=~s/&gt;/>/g;
15062
15063 $Str=~s/&quot;/"/g;
15064 $Str=~s/&#39;/'/g;
15065
15066 return $Str;
15067}
15068
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015069sub black_name($)
15070{
15071 my $Name = $_[0];
15072 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15073}
15074
15075sub highLight_Signature($)
15076{
15077 my $Signature = $_[0];
15078 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15079}
15080
15081sub highLight_Signature_Italic_Color($)
15082{
15083 my $Signature = $_[0];
15084 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15085}
15086
15087sub separate_symbol($)
15088{
15089 my $Symbol = $_[0];
15090 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15091 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15092 ($Name, $Spec, $Ver) = ($1, $2, $3);
15093 }
15094 return ($Name, $Spec, $Ver);
15095}
15096
15097sub cut_f_attrs($)
15098{
15099 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15100 return $2;
15101 }
15102 return "";
15103}
15104
15105sub highLight_Signature_PPos_Italic($$$$$)
15106{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015107 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15108 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015109 if($CheckObjectsOnly) {
15110 $ItalicParams=$ColorParams=0;
15111 }
15112 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15113 my $Return = "";
15114 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15115 $Return = $2;
15116 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015117 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015118 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015119 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015120 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015121 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015122 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015123 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015124 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015125 }
15126 return $Signature;
15127 }
15128 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15129 $Begin.=" " if($Begin!~/ \Z/);
15130 $End = cut_f_attrs($Signature);
15131 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015132 my ($Short, $Params) = split_Signature($Signature);
15133 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015134 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015135 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015136 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015137 $Part=~s/\A\s+|\s+\Z//g;
15138 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15139 if($Part=~/\([\*]+(\w+)\)/i) {
15140 $ParamName = $1;#func-ptr
15141 }
15142 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15143 $ParamName = $1;
15144 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015145 if(not $ParamName)
15146 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015147 push(@Parts, $Part_Styled);
15148 next;
15149 }
15150 if($ItalicParams and not $TName_Tid{1}{$Part}
15151 and not $TName_Tid{2}{$Part})
15152 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015153 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015154 if($Param_Pos ne ""
15155 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015156 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015157 }
15158 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015159 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015160 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015161 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015162 }
15163 $Part_Styled=~s/,(\w)/, $1/g;
15164 push(@Parts, $Part_Styled);
15165 }
15166 if(@Parts)
15167 {
15168 foreach my $Num (0 .. $#Parts)
15169 {
15170 if($Num==$#Parts)
15171 { # add ")" to the last parameter
15172 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15173 }
15174 elsif(length($Parts[$Num])<=45) {
15175 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15176 }
15177 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015178 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015179 }
15180 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015181 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015182 }
15183 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015184 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015185 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015186 $Signature=~s!\[\]![&#160;]!g;
15187 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015188 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15189 if($SymbolVersion) {
15190 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15191 }
15192 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015193}
15194
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015195sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015196{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015197 my $Signature = $_[0];
15198 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15199 {
15200 $Signature=~s/\A\Q$ShortName\E\(//g;
15201 cut_f_attrs($Signature);
15202 $Signature=~s/\)\Z//;
15203 return ($ShortName, $Signature);
15204 }
15205
15206 # error
15207 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015208}
15209
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015210sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015211{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015212 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015213 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015214 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15215 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015216 foreach my $Pos (0 .. length($Params) - 1)
15217 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015218 my $S = substr($Params, $Pos, 1);
15219 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015220 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015221 }
15222 if($S eq "," and
15223 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015224 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015225 if($Comma)
15226 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015227 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015228 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015229 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015230 }
15231 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015232 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015233 }
15234 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015235 if(not $Sp)
15236 { # remove spaces
15237 foreach (@Parts)
15238 {
15239 s/\A //g;
15240 s/ \Z//g;
15241 }
15242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015243 return @Parts;
15244}
15245
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015246sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015247{
15248 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015249 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015250 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015251 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15252 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015253 $Center+=length($1);
15254 }
15255 foreach my $Pos (0 .. length($Sign)-1)
15256 {
15257 my $S = substr($Sign, $Pos, 1);
15258 if($S eq $Target)
15259 {
15260 if($B{"("}==$B{")"}
15261 and $B{"<"}==$B{">"}) {
15262 return $Center;
15263 }
15264 }
15265 if(defined $B{$S}) {
15266 $B{$S}+=1;
15267 }
15268 $Center+=1;
15269 }
15270 return 0;
15271}
15272
15273sub appendFile($$)
15274{
15275 my ($Path, $Content) = @_;
15276 return if(not $Path);
15277 if(my $Dir = get_dirname($Path)) {
15278 mkpath($Dir);
15279 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015280 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015281 print FILE $Content;
15282 close(FILE);
15283}
15284
15285sub writeFile($$)
15286{
15287 my ($Path, $Content) = @_;
15288 return if(not $Path);
15289 if(my $Dir = get_dirname($Path)) {
15290 mkpath($Dir);
15291 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015292 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015293 print FILE $Content;
15294 close(FILE);
15295}
15296
15297sub readFile($)
15298{
15299 my $Path = $_[0];
15300 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015301 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015302 local $/ = undef;
15303 my $Content = <FILE>;
15304 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015305 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015306 $Content=~s/\r/\n/g;
15307 }
15308 return $Content;
15309}
15310
15311sub get_filename($)
15312{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015313 if(defined $Cache{"get_filename"}{$_[0]}) {
15314 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015315 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015316 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15317 return ($Cache{"get_filename"}{$_[0]}=$1);
15318 }
15319 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015320}
15321
15322sub get_dirname($)
15323{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015324 if(defined $Cache{"get_dirname"}{$_[0]}) {
15325 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015326 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015327 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15328 return ($Cache{"get_dirname"}{$_[0]}=$1);
15329 }
15330 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015331}
15332
15333sub separate_path($) {
15334 return (get_dirname($_[0]), get_filename($_[0]));
15335}
15336
15337sub esc($)
15338{
15339 my $Str = $_[0];
15340 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15341 return $Str;
15342}
15343
15344sub readLineNum($$)
15345{
15346 my ($Path, $Num) = @_;
15347 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015348 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015349 foreach (1 ... $Num) {
15350 <FILE>;
15351 }
15352 my $Line = <FILE>;
15353 close(FILE);
15354 return $Line;
15355}
15356
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015357sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015358{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015359 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015360 return () if(not $Path or not -f $Path);
15361 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015362 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15363 {
15364 foreach my $AttrVal (split(/;/, $1))
15365 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015366 if($AttrVal=~/(.+):(.+)/)
15367 {
15368 my ($Name, $Value) = ($1, $2);
15369 $Attributes{$Name} = $Value;
15370 }
15371 }
15372 }
15373 return \%Attributes;
15374}
15375
15376sub is_abs($) {
15377 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15378}
15379
15380sub get_abs_path($)
15381{ # abs_path() should NOT be called for absolute inputs
15382 # because it can change them
15383 my $Path = $_[0];
15384 if(not is_abs($Path)) {
15385 $Path = abs_path($Path);
15386 }
15387 return $Path;
15388}
15389
15390sub get_OSgroup()
15391{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015392 my $N = $Config{"osname"};
15393 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015394 return "macos";
15395 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015396 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015397 return "bsd";
15398 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015399 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015400 return "beos";
15401 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015402 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015403 return "symbian";
15404 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015405 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015406 return "windows";
15407 }
15408 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015409 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015410 }
15411}
15412
15413sub getGccVersion($)
15414{
15415 my $LibVersion = $_[0];
15416 if($GCC_VERSION{$LibVersion})
15417 { # dump version
15418 return $GCC_VERSION{$LibVersion};
15419 }
15420 elsif($UsedDump{$LibVersion}{"V"})
15421 { # old-version dumps
15422 return "unknown";
15423 }
15424 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15425 if(not $GccVersion) {
15426 return "unknown";
15427 }
15428 return $GccVersion;
15429}
15430
15431sub showArch($)
15432{
15433 my $Arch = $_[0];
15434 if($Arch eq "arm"
15435 or $Arch eq "mips") {
15436 return uc($Arch);
15437 }
15438 return $Arch;
15439}
15440
15441sub getArch($)
15442{
15443 my $LibVersion = $_[0];
15444 if($CPU_ARCH{$LibVersion})
15445 { # dump version
15446 return $CPU_ARCH{$LibVersion};
15447 }
15448 elsif($UsedDump{$LibVersion}{"V"})
15449 { # old-version dumps
15450 return "unknown";
15451 }
15452 if(defined $Cache{"getArch"}{$LibVersion}) {
15453 return $Cache{"getArch"}{$LibVersion};
15454 }
15455 my $Arch = get_dumpmachine($GCC_PATH); # host version
15456 if(not $Arch) {
15457 return "unknown";
15458 }
15459 if($Arch=~/\A([\w]{3,})(-|\Z)/) {
15460 $Arch = $1;
15461 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040015462 $Arch = "x86" if($Arch=~/\Ai[3-7]86\Z/i);
15463 $Arch = "x86_64" if($Arch=~/\Aamd64\Z/i);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040015464 if($OSgroup eq "windows")
15465 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015466 $Arch = "x86" if($Arch=~/win32|mingw32/i);
15467 $Arch = "x86_64" if($Arch=~/win64|mingw64/i);
15468 }
15469 $Cache{"getArch"}{$LibVersion} = $Arch;
15470 return $Arch;
15471}
15472
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015473sub get_Report_Header($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015474{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015475 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015476 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015477 if(getArch(1) ne getArch(2)
15478 or getArch(1) eq "unknown"
15479 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015480 { # don't show architecture in the header
15481 $ArchInfo="";
15482 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015483 my $Report_Header = "<h1><span class='nowrap'>";
15484 if($Level eq "Source") {
15485 $Report_Header .= "Source compatibility";
15486 }
15487 elsif($Level eq "Binary") {
15488 $Report_Header .= "Binary compatibility";
15489 }
15490 else {
15491 $Report_Header .= "API compatibility";
15492 }
15493 $Report_Header .= " report for the <span style='color:Blue;'>$TargetLibraryFName</span> $TargetComponent</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015494 $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>";
15495 if($AppPath) {
15496 $Report_Header .= " <span class='nowrap'>&#160;(relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)</span>";
15497 }
15498 $Report_Header .= "</h1>\n";
15499 return $Report_Header;
15500}
15501
15502sub get_SourceInfo()
15503{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015504 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015505 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015506 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015507 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015508 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015509 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15510 $CheckedHeaders .= "<div class='h_list'>\n";
15511 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15512 {
15513 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15514 my $Name = get_filename($Identity);
15515 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15516 $CheckedHeaders .= $Name.$Comment."<br/>\n";
15517 }
15518 $CheckedHeaders .= "</div>\n";
15519 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015520 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015521
15522 if(my @Sources = keys(%{$Registered_Sources{1}}))
15523 {
15524 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15525 $CheckedSources .= "<div class='h_list'>\n";
15526 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15527 {
15528 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15529 my $Name = get_filename($Identity);
15530 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15531 $CheckedSources .= $Name.$Comment."<br/>\n";
15532 }
15533 $CheckedSources .= "</div>\n";
15534 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15535 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015536 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015537 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015538 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015539 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015540 $CheckedLibs .= "<div class='lib_list'>\n";
15541 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15542 {
15543 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15544 $CheckedLibs .= $Library."<br/>\n";
15545 }
15546 $CheckedLibs .= "</div>\n";
15547 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015548 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015549 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15550}
15551
15552sub get_ObjTitle()
15553{
15554 if(defined $UsedDump{1}{"DWARF"}) {
15555 return "Objects";
15556 }
15557 else {
15558 return ucfirst($SLIB_TYPE)." Libraries";
15559 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015560}
15561
15562sub get_TypeProblems_Count($$$)
15563{
15564 my ($TypeChanges, $TargetPriority, $Level) = @_;
15565 my $Type_Problems_Count = 0;
15566 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15567 {
15568 my %Kinds_Target = ();
15569 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15570 {
15571 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15572 {
15573 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
15574 my $Priority = getProblemSeverity($Level, $Kind);
15575 next if($Priority ne $TargetPriority);
15576 if($Kinds_Target{$Kind}{$Target}) {
15577 next;
15578 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015579 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015580 { # select a problem with the highest priority
15581 next;
15582 }
15583 $Kinds_Target{$Kind}{$Target} = 1;
15584 $Type_Problems_Count += 1;
15585 }
15586 }
15587 }
15588 return $Type_Problems_Count;
15589}
15590
15591sub get_Summary($)
15592{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015593 my $Level = $_[0];
15594 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015595 $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 +040015596 %{$RESULT{$Level}} = (
15597 "Problems"=>0,
15598 "Warnings"=>0,
15599 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015600 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015601 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015602 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015603 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015604 {
15605 if(not defined $CompatRules{$Level}{$Kind})
15606 { # unknown rule
15607 if(not $UnknownRules{$Level}{$Kind})
15608 { # only one warning
15609 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15610 $UnknownRules{$Level}{$Kind}=1;
15611 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015612 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015613 }
15614 }
15615 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015616 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15617 {
15618 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15619 {
15620 if(not defined $CompatRules{$Level}{$Kind})
15621 { # unknown rule
15622 if(not $UnknownRules{$Level}{$Kind})
15623 { # only one warning
15624 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15625 $UnknownRules{$Level}{$Kind}=1;
15626 }
15627 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15628 }
15629 }
15630 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015631 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015632 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015633 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015634 {
15635 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15636 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015637 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015638 {
15639 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015640 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015641 $Added += 1;
15642 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015643 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015644 {
15645 $Removed += 1;
15646 $TotalAffected{$Level}{$Interface} = $Priority;
15647 }
15648 else
15649 {
15650 if($Priority eq "Safe") {
15651 $I_Other += 1;
15652 }
15653 elsif($Priority eq "High") {
15654 $I_Problems_High += 1;
15655 }
15656 elsif($Priority eq "Medium") {
15657 $I_Problems_Medium += 1;
15658 }
15659 elsif($Priority eq "Low") {
15660 $I_Problems_Low += 1;
15661 }
15662 if(($Priority ne "Low" or $StrictCompat)
15663 and $Priority ne "Safe") {
15664 $TotalAffected{$Level}{$Interface} = $Priority;
15665 }
15666 }
15667 }
15668 }
15669 }
15670 }
15671 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015672 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015673 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015674 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015675 {
15676 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15677 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015678 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015679 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015680 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15681 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015682 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015683 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015684 { # select a problem with the highest priority
15685 next;
15686 }
15687 if(($Priority ne "Low" or $StrictCompat)
15688 and $Priority ne "Safe") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015689 $TotalAffected{$Level}{$Interface} = maxSeverity($TotalAffected{$Level}{$Interface}, $Priority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015690 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015691 %{$TypeChanges{$Type_Name}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015692 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = maxSeverity($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015693 }
15694 }
15695 }
15696 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015697
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015698 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15699 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15700 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15701 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015702
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015703 if($CheckObjectsOnly)
15704 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015705 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015706 }
15707 else
15708 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015709 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015710 if($ExtendedCheck)
15711 { # don't count external_func_0 for constants
15712 $SCount-=1;
15713 }
15714 if($SCount)
15715 {
15716 my %Weight = (
15717 "High" => 100,
15718 "Medium" => 50,
15719 "Low" => 25
15720 );
15721 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015722 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015723 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015724 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015725 }
15726 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015727 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015728 }
15729 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015730 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15731 if($RESULT{$Level}{"Affected"}>=100) {
15732 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015733 }
15734
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015735 $RESULT{$Level}{"Problems"} += $Removed;
15736 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015737 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015738 if($StrictCompat) {
15739 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15740 }
15741 else {
15742 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15743 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015744
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015745 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015746 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015747 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015748 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015749 my $Severity = getProblemSeverity($Level, $Kind);
15750 if($Severity eq "Safe")
15751 {
15752 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015753 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015754 elsif($Severity eq "Low")
15755 {
15756 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015757 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015758 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015759 }
15760
15761 if($C_Problems_Low)
15762 {
15763 if($StrictCompat) {
15764 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15765 }
15766 else {
15767 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015768 }
15769 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015770 if($CheckImpl and $Level eq "Binary")
15771 {
15772 if($StrictCompat) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015773 $RESULT{$Level}{"Problems"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015774 }
15775 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015776 $RESULT{$Level}{"Warnings"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015777 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015778 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015779 if($RESULT{$Level}{"Problems"}
15780 and $RESULT{$Level}{"Affected"}) {
15781 $RESULT{$Level}{"Verdict"} = "incompatible";
15782 }
15783 else {
15784 $RESULT{$Level}{"Verdict"} = "compatible";
15785 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015786
15787 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15788 if(not $TotalTypes)
15789 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015790 $TotalTypes = keys(%{$TName_Tid{1}});
15791 }
15792
15793 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15794 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15795
15796 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15797
15798 if($ReportFormat eq "xml")
15799 { # XML
15800 # test info
15801 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15802 $TestInfo .= " <version1>\n";
15803 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
15804 $TestInfo .= " <architecture>$Arch1</architecture>\n";
15805 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15806 $TestInfo .= " </version1>\n";
15807
15808 $TestInfo .= " <version2>\n";
15809 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
15810 $TestInfo .= " <architecture>$Arch2</architecture>\n";
15811 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15812 $TestInfo .= " </version2>\n";
15813 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15814
15815 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015816 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015817 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015818 $TestResults .= " <headers>\n";
15819 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15820 {
15821 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15822 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15823 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15824 }
15825 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015826 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015827
15828 if(my @Sources = keys(%{$Registered_Sources{1}}))
15829 {
15830 $TestResults .= " <sources>\n";
15831 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15832 {
15833 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15834 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15835 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15836 }
15837 $TestResults .= " </sources>\n";
15838 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015839
15840 $TestResults .= " <libs>\n";
15841 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15842 {
15843 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15844 $TestResults .= " <name>$Library</name>\n";
15845 }
15846 $TestResults .= " </libs>\n";
15847
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015848 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015849 $TestResults .= " <types>".$TotalTypes."</types>\n";
15850
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015851 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15852 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015853 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15854
15855 # problem summary
15856 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15857 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15858
15859 $Problem_Summary .= " <problems_with_types>\n";
15860 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15861 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15862 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15863 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15864 $Problem_Summary .= " </problems_with_types>\n";
15865
15866 $Problem_Summary .= " <problems_with_symbols>\n";
15867 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15868 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15869 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015870 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015871 $Problem_Summary .= " </problems_with_symbols>\n";
15872
15873 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015874 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015875 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015876 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015877 {
15878 $Problem_Summary .= " <impl>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015879 $Problem_Summary .= " <low>".keys(%CompatProblems_Impl)."</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015880 $Problem_Summary .= " </impl>\n";
15881 }
15882 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15883
15884 return ($TestInfo.$TestResults.$Problem_Summary, "");
15885 }
15886 else
15887 { # HTML
15888 # test info
15889 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015890 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015891 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetLibraryFName</td></tr>\n";
15892
15893 my (@VInf1, @VInf2, $AddTestInfo) = ();
15894 if($Arch1 ne "unknown"
15895 and $Arch2 ne "unknown")
15896 { # CPU arch
15897 if($Arch1 eq $Arch2)
15898 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015899 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015900 }
15901 else
15902 { # go to the version number
15903 push(@VInf1, showArch($Arch1));
15904 push(@VInf2, showArch($Arch2));
15905 }
15906 }
15907 if($GccV1 ne "unknown"
15908 and $GccV2 ne "unknown"
15909 and $OStarget ne "windows")
15910 { # GCC version
15911 if($GccV1 eq $GccV2)
15912 { # go to the separate section
15913 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15914 }
15915 else
15916 { # go to the version number
15917 push(@VInf1, "gcc ".$GccV1);
15918 push(@VInf2, "gcc ".$GccV2);
15919 }
15920 }
15921 # show long version names with GCC version and CPU architecture name (if different)
15922 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15923 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15924 $TestInfo .= $AddTestInfo;
15925 #if($COMMON_LANGUAGE{1}) {
15926 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15927 #}
15928 if($ExtendedCheck) {
15929 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15930 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015931 if($JoinReport)
15932 {
15933 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015934 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015935 }
15936 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015937 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015938 }
15939 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015940 $TestInfo .= "</table>\n";
15941
15942 # test results
15943 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015944 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015945
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015946 if(my @Headers = keys(%{$Registered_Headers{1}}))
15947 {
15948 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15949 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15950 }
15951 elsif($CheckObjectsOnly) {
15952 $TestResults .= "<tr><th>Total Header Files</th><td>0&#160;(not&#160;analyzed)</td></tr>\n";
15953 }
15954
15955 if(my @Sources = keys(%{$Registered_Sources{1}}))
15956 {
15957 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15958 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15959 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015960
15961 if(not $ExtendedCheck)
15962 {
15963 my $Libs_Link = "0";
15964 $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 +040015965 $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 +040015966 }
15967
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015968 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015969
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015970 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015971 if($JoinReport) {
15972 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15973 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015974 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015975 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015976 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15977 }
15978 else {
15979 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15980 }
15981 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015982 $TestResults .= "</table>\n";
15983
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015984 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015985 # problem summary
15986 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015987 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015988 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15989
15990 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015991 if($Added>0)
15992 {
15993 if($JoinReport) {
15994 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15995 }
15996 else {
15997 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15998 }
15999 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016000 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016001 $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 +040016002
16003 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016004 if($Removed>0)
16005 {
16006 if($JoinReport) {
16007 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16008 }
16009 else {
16010 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16011 }
16012 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016013 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016014 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
16015 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016016
16017 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016018 $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 +040016019 $TH_Link = "n/a" if($CheckObjectsOnly);
16020 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016021 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
16022 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016023
16024 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016025 $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 +040016026 $TM_Link = "n/a" if($CheckObjectsOnly);
16027 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016028 $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 +040016029
16030 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016031 $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 +040016032 $TL_Link = "n/a" if($CheckObjectsOnly);
16033 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016034 $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 +040016035
16036 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016037 $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 +040016038 $IH_Link = "n/a" if($CheckObjectsOnly);
16039 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016040 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
16041 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016042
16043 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016044 $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 +040016045 $IM_Link = "n/a" if($CheckObjectsOnly);
16046 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016047 $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 +040016048
16049 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016050 $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 +040016051 $IL_Link = "n/a" if($CheckObjectsOnly);
16052 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016053 $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 +040016054
16055 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016056 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16057 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016058 }
16059 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016060 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016061 $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 +040016062
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016063 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016064 {
16065 my $ChangedImpl_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016066 $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 +040016067 $ChangedImpl_Link = "n/a" if($CheckHeadersOnly);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016068 $META_DATA .= "changed_implementation:".keys(%CompatProblems_Impl).";";
16069 $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 +040016070 }
16071 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016072 if($T_Other and not $CheckObjectsOnly)
16073 {
16074 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016075 $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 +040016076 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016077
16078 if($I_Other and not $CheckObjectsOnly)
16079 {
16080 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016081 $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 +040016082 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016083
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016084 if($C_Other and not $CheckObjectsOnly)
16085 {
16086 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16087 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
16088 }
16089
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016090 $META_DATA .= "tool_version:$TOOL_VERSION";
16091 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016092 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016093 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16094 }
16095}
16096
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016097sub getStyle($$$)
16098{
16099 my ($Subj, $Act, $Num) = @_;
16100 my %Style = (
16101 "A"=>"new",
16102 "R"=>"failed",
16103 "S"=>"passed",
16104 "L"=>"warning",
16105 "M"=>"failed",
16106 "H"=>"failed"
16107 );
16108 if($Num>0) {
16109 return " class='".$Style{$Act}."'";
16110 }
16111 return "";
16112}
16113
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016114sub show_number($)
16115{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016116 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016117 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016118 my $Num = cut_off_number($_[0], 2, 0);
16119 if($Num eq "0")
16120 {
16121 foreach my $P (3 .. 7)
16122 {
16123 $Num = cut_off_number($_[0], $P, 1);
16124 if($Num ne "0") {
16125 last;
16126 }
16127 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016128 }
16129 if($Num eq "0") {
16130 $Num = $_[0];
16131 }
16132 return $Num;
16133 }
16134 return $_[0];
16135}
16136
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016137sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016138{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016139 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016140 if($num!~/\./)
16141 {
16142 $num .= ".";
16143 foreach (1 .. $digs_to_cut-1) {
16144 $num .= "0";
16145 }
16146 }
16147 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16148 {
16149 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16150 $num .= "0";
16151 }
16152 }
16153 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16154 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16155 }
16156 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016157 if($z) {
16158 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16159 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016160 return $num;
16161}
16162
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016163sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016164{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016165 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016166 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016167
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016168 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016169 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16170 {
16171 my $Header = $Constants{1}{$Constant}{"Header"};
16172 if(not $Header)
16173 { # added
16174 $Header = $Constants{2}{$Constant}{"Header"}
16175 }
16176
16177 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16178 {
16179 if(not defined $CompatRules{$Level}{$Kind}) {
16180 next;
16181 }
16182 if($TargetSeverity ne getProblemSeverity($Level, $Kind)) {
16183 next;
16184 }
16185 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16186 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016187 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016188
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016189 if($ReportFormat eq "xml")
16190 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016191 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016192 {
16193 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016194 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016195 {
16196 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016197 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16198 {
16199 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16200 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16201 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016202
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016203 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16204 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16205 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
16206 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16207 $CHANGED_CONSTANTS .= " </problem>\n";
16208 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016209 $CHANGED_CONSTANTS .= " </constant>\n";
16210 }
16211 $CHANGED_CONSTANTS .= " </header>\n";
16212 }
16213 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16214 }
16215 else
16216 { # HTML
16217 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016218 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016219 {
16220 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016221 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016222 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016223 my $Report = "";
16224
16225 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16226 {
16227 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16228 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16229 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16230 $Number += 1;
16231 }
16232 if($Report)
16233 {
16234 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16235 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16236 $Report = insertIDs($Report);
16237 }
16238 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016239 }
16240 $CHANGED_CONSTANTS .= "<br/>\n";
16241 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016242 if($CHANGED_CONSTANTS)
16243 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016244 my $Title = "Problems with Constants, $TargetSeverity Severity";
16245 if($TargetSeverity eq "Safe")
16246 { # Safe Changes
16247 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016248 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016249 $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 +040016250 }
16251 }
16252 return $CHANGED_CONSTANTS;
16253}
16254
16255sub get_Report_Impl()
16256{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016257 my $CHANGED_IMPLEMENTATION = "";
16258 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016259 foreach my $Interface (sort keys(%CompatProblems_Impl))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016260 {
16261 my $HeaderName = $CompleteSignature{1}{$Interface}{"Header"};
16262 my $DyLib = $Symbol_Library{1}{$Interface};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016263 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016264 }
16265 my $Changed_Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016266 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016267 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016268 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016269 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016270 my %NameSpaceSymbols = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016271 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016272 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016273 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016274 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016275 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016276 $CHANGED_IMPLEMENTATION .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016277 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016278 foreach my $Interface (@SortedInterfaces)
16279 {
16280 $Changed_Number += 1;
16281 my $Signature = get_Signature($Interface, 1);
16282 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016283 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016284 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016285 $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 +040016286 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016287 $CHANGED_IMPLEMENTATION .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016288 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016289 }
16290 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016291 if($CHANGED_IMPLEMENTATION)
16292 {
16293 $CHANGED_IMPLEMENTATION = insertIDs($CHANGED_IMPLEMENTATION);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016294 $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 +040016295 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016296
16297 # clean memory
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016298 %CompatProblems_Impl = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016299
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016300 return $CHANGED_IMPLEMENTATION;
16301}
16302
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016303sub getTitle($$$)
16304{
16305 my ($Header, $Library, $NameSpace) = @_;
16306 my $Title = "";
16307 if($Library and $Library!~/\.\w+\Z/) {
16308 $Library .= " (.$LIB_EXT)";
16309 }
16310 if($Header and $Library)
16311 {
16312 $Title .= "<span class='h_name'>$Header</span>";
16313 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16314 }
16315 elsif($Library) {
16316 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16317 }
16318 elsif($Header) {
16319 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16320 }
16321 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016322 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016323 }
16324 return $Title;
16325}
16326
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016327sub get_Report_Added($)
16328{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016329 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016330 my $ADDED_INTERFACES = "";
16331 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016332 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016333 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016334 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016335 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016336 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016337 {
16338 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16339 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016340 if($Level eq "Source" and $ReportFormat eq "html")
16341 { # do not show library name in HTML report
16342 $DyLib = "";
16343 }
16344 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016345 }
16346 }
16347 }
16348 if($ReportFormat eq "xml")
16349 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016350 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016351 {
16352 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016353 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016354 {
16355 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016356 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016357 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16358 }
16359 $ADDED_INTERFACES .= " </library>\n";
16360 }
16361 $ADDED_INTERFACES .= " </header>\n";
16362 }
16363 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16364 }
16365 else
16366 { # HTML
16367 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016368 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016369 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016370 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016371 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016372 my %NameSpaceSymbols = ();
16373 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016374 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016375 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016376 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016377 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016378 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16379 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016380 foreach my $Interface (@SortedInterfaces)
16381 {
16382 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016383 my $Signature = get_Signature($Interface, 2);
16384 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016385 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016386 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016387 if($Interface=~/\A(_Z|\?)/)
16388 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016389 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016390 $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 +040016391 }
16392 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016393 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016394 }
16395 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016396 else
16397 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016398 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016399 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016400 }
16401 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016402 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016403 }
16404 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016405 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016406 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016407 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016408 }
16409 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016410 if($ADDED_INTERFACES)
16411 {
16412 my $Anchor = "<a name='Added'></a>";
16413 if($JoinReport) {
16414 $Anchor = "<a name='".$Level."_Added'></a>";
16415 }
16416 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016417 }
16418 }
16419 return $ADDED_INTERFACES;
16420}
16421
16422sub get_Report_Removed($)
16423{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016424 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016425 my $REMOVED_INTERFACES = "";
16426 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016427 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016428 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016429 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016430 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016431 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016432 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016433 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16434 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016435 if($Level eq "Source" and $ReportFormat eq "html")
16436 { # do not show library name in HTML report
16437 $DyLib = "";
16438 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016439 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016440 }
16441 }
16442 }
16443 if($ReportFormat eq "xml")
16444 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016445 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016446 {
16447 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016448 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016449 {
16450 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016451 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16452 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016453 }
16454 $REMOVED_INTERFACES .= " </library>\n";
16455 }
16456 $REMOVED_INTERFACES .= " </header>\n";
16457 }
16458 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16459 }
16460 else
16461 { # HTML
16462 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016463 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016464 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016465 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016466 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016467 my %NameSpaceSymbols = ();
16468 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016469 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016470 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016471 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016472 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016473 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16474 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016475 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016476 {
16477 $Removed_Number += 1;
16478 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016479 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016480 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016481 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016482 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016483 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016484 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016485 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016486 $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 +040016487 }
16488 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016489 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016490 }
16491 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016492 else
16493 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016494 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016495 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016496 }
16497 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016498 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016499 }
16500 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016501 }
16502 }
16503 $REMOVED_INTERFACES .= "<br/>\n";
16504 }
16505 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016506 if($REMOVED_INTERFACES)
16507 {
16508 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16509 if($JoinReport) {
16510 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16511 }
16512 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016513 }
16514 }
16515 return $REMOVED_INTERFACES;
16516}
16517
16518sub getXmlParams($$)
16519{
16520 my ($Content, $Problem) = @_;
16521 return "" if(not $Content or not $Problem);
16522 my %XMLparams = ();
16523 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16524 {
16525 my $Macro = "\@".lc($Attr);
16526 if($Content=~/\Q$Macro\E/) {
16527 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16528 }
16529 }
16530 my @PString = ();
16531 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016532 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016533 }
16534 if(@PString) {
16535 return " ".join(" ", @PString);
16536 }
16537 else {
16538 return "";
16539 }
16540}
16541
16542sub addMarkup($)
16543{
16544 my $Content = $_[0];
16545 # auto-markup
16546 $Content=~s/\n[ ]*//; # spaces
16547 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16548 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016549 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016550 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16551 if($Content=~/\ANOTE:/)
16552 { # notes
16553 $Content=~s!(NOTE):!<b>$1</b>:!g;
16554 }
16555 else {
16556 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16557 }
16558 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16559 my @Keywords = (
16560 "void",
16561 "const",
16562 "static",
16563 "restrict",
16564 "volatile",
16565 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016566 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016567 );
16568 my $MKeys = join("|", @Keywords);
16569 foreach (@Keywords) {
16570 $MKeys .= "|non-".$_;
16571 }
16572 $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 +040016573
16574 # Markdown
16575 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16576 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016577 return $Content;
16578}
16579
16580sub applyMacroses($$$$)
16581{
16582 my ($Level, $Kind, $Content, $Problem) = @_;
16583 return "" if(not $Content or not $Problem);
16584 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16585 $Content = addMarkup($Content);
16586 # macros
16587 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16588 {
16589 my $Macro = "\@".lc($Attr);
16590 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016591 if(not defined $Value
16592 or $Value eq "") {
16593 next;
16594 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016595 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016596 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016597 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
16598 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016599 $Value = black_name($Value);
16600 }
16601 elsif($Value=~/\s/) {
16602 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16603 }
16604 elsif($Value=~/\A\d+\Z/
16605 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16606 { # bits to bytes
16607 if($Value % $BYTE_SIZE)
16608 { # bits
16609 if($Value==1) {
16610 $Value = "<b>".$Value."</b> bit";
16611 }
16612 else {
16613 $Value = "<b>".$Value."</b> bits";
16614 }
16615 }
16616 else
16617 { # bytes
16618 $Value /= $BYTE_SIZE;
16619 if($Value==1) {
16620 $Value = "<b>".$Value."</b> byte";
16621 }
16622 else {
16623 $Value = "<b>".$Value."</b> bytes";
16624 }
16625 }
16626 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016627 else
16628 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016629 $Value = "<b>".htmlSpecChars($Value)."</b>";
16630 }
16631 $Content=~s/\Q$Macro\E/$Value/g;
16632 }
16633
16634 if($Content=~/(\A|[^\@\w])\@\w/)
16635 {
16636 if(not $IncompleteRules{$Level}{$Kind})
16637 { # only one warning
16638 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16639 $IncompleteRules{$Level}{$Kind} = 1;
16640 }
16641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016642 return $Content;
16643}
16644
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016645sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016646{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016647 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016648 my $INTERFACE_PROBLEMS = "";
16649 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016650 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016651 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016652 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16653 if($SV and defined $CompatProblems{$Level}{$SN}) {
16654 next;
16655 }
16656 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016657 {
16658 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016659 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016660 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016661 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16662 my $DyLib = $Symbol_Library{1}{$Symbol};
16663 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016664 { # Symbol with Version
16665 $DyLib = $Symbol_Library{1}{$VSym};
16666 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016667 if(not $DyLib)
16668 { # const global data
16669 $DyLib = "";
16670 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016671 if($Level eq "Source" and $ReportFormat eq "html")
16672 { # do not show library name in HTML report
16673 $DyLib = "";
16674 }
16675 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16676 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016677 {
16678 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016679 if($Priority ne $TargetSeverity) {
16680 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016681 }
16682 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016683 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16684 {
16685 delete($SymbolChanges{$Symbol}{$Kind});
16686 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016687 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016688 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016689 }
16690 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016691 if(not keys(%{$SymbolChanges{$Symbol}})) {
16692 delete($SymbolChanges{$Symbol});
16693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016694 }
16695 if($ReportFormat eq "xml")
16696 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016697 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016698 {
16699 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016700 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016701 {
16702 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016703 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 +040016704 {
16705 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16706 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16707 {
16708 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16709 {
16710 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016711 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016712 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16713 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16714 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16715 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16716 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
16717 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
16718 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16719 $INTERFACE_PROBLEMS .= " </problem>\n";
16720 }
16721 }
16722 $INTERFACE_PROBLEMS .= " </symbol>\n";
16723 }
16724 $INTERFACE_PROBLEMS .= " </library>\n";
16725 }
16726 $INTERFACE_PROBLEMS .= " </header>\n";
16727 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016728 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016729 }
16730 else
16731 { # HTML
16732 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016733 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016734 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016735 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016736 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016737 my (%NameSpaceSymbols, %NewSignature) = ();
16738 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016739 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016740 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016741 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016742 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016743 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016744 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 +040016745 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016746 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016747 my $Signature = get_Signature($Symbol, 1);
16748 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016749 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016750 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016751 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016752 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016753 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016754 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016755 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016756 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016757 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016758 }
16759 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16760 {
16761 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016762 $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 +040016763 $ProblemNum += 1;
16764 $ProblemsNum += 1;
16765 }
16766 }
16767 }
16768 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016769 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016770 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016771 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016772 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016773 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016774 }
16775 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016776 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016777 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016778 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16779 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16780 if($NewSignature{$Symbol})
16781 { # argument list changed to
16782 $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 +040016783 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016784 if($Symbol=~/\A(_Z|\?)/) {
16785 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16786 }
16787 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16788 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016789 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016790 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016791 }
16792 }
16793 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016794 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016795 }
16796 }
16797 }
16798 if($INTERFACE_PROBLEMS)
16799 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016800 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16801 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16802 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016803 { # Safe Changes
16804 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016805 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016806 $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 +040016807 }
16808 }
16809 return $INTERFACE_PROBLEMS;
16810}
16811
16812sub get_Report_TypeProblems($$)
16813{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016814 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016815 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016816 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016817 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016818 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016819 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016820 {
16821 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16822 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016823 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016824 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016825 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016826 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016827 my $Severity = getProblemSeverity($Level, $Kind);
16828 if($Severity eq "Safe"
16829 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016830 next;
16831 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016832
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016833 if(cmpSeverities($Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target}, $Severity))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016834 { # select a problem with the highest priority
16835 next;
16836 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016837 %{$TypeChanges{$TypeName}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016838 }
16839 }
16840 }
16841 }
16842 my %Kinds_Locations = ();
16843 foreach my $TypeName (keys(%TypeChanges))
16844 {
16845 my %Kinds_Target = ();
16846 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16847 {
16848 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16849 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016850 my $Severity = getProblemSeverity($Level, $Kind);
16851 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016852 { # other priority
16853 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16854 next;
16855 }
16856 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16857 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
16858 if($Kinds_Target{$Kind}{$Target})
16859 { # duplicate target
16860 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16861 next;
16862 }
16863 $Kinds_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016864 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016865 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016866 }
16867 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16868 delete($TypeChanges{$TypeName}{$Kind});
16869 }
16870 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016871 if(not keys(%{$TypeChanges{$TypeName}})) {
16872 delete($TypeChanges{$TypeName});
16873 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016874 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016875 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 +040016876 if($ReportFormat eq "xml")
16877 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016878 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016879 {
16880 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016881 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016882 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016883 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016884 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16885 {
16886 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16887 {
16888 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16889 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16890 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16891 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16892 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16893 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
16894 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
16895 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16896 $TYPE_PROBLEMS .= " </problem>\n";
16897 }
16898 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016899 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016900 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016901 $TYPE_PROBLEMS .= showVTables($TypeName);
16902 }
16903 $TYPE_PROBLEMS .= " </type>\n";
16904 }
16905 $TYPE_PROBLEMS .= " </header>\n";
16906 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016907 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016908 }
16909 else
16910 { # HTML
16911 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016912 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016913 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016914 my (%NameSpace_Type) = ();
16915 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016916 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016917 }
16918 foreach my $NameSpace (sort keys(%NameSpace_Type))
16919 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016920 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016921 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 +040016922 foreach my $TypeName (@SortedTypes)
16923 {
16924 my $ProblemNum = 1;
16925 my $TYPE_REPORT = "";
16926 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16927 {
16928 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16929 {
16930 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16931 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16932 {
16933 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
16934 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16935 $ProblemNum += 1;
16936 $ProblemsNum += 1;
16937 }
16938 }
16939 }
16940 $ProblemNum -= 1;
16941 if($TYPE_REPORT)
16942 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016943 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016944 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016945 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016946 $ShowVTables = showVTables($TypeName);
16947 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016948
16949 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016950 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16951 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16952 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16953 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016954 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016955 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016956 }
16957 }
16958 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016959 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016960 }
16961 }
16962 if($TYPE_PROBLEMS)
16963 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016964 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16965 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016966 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016967 { # Safe Changes
16968 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016969 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016970 $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 +040016971 }
16972 }
16973 return $TYPE_PROBLEMS;
16974}
16975
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016976sub show_Type($$$)
16977{
16978 my ($Name, $Html, $LibVersion) = @_;
16979 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16980 $TType = lc($TType);
16981 if($TType=~/struct|union|enum/) {
16982 $Name=~s/\A\Q$TType\E //g;
16983 }
16984 if($Html) {
16985 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16986 }
16987 else {
16988 $Name = $TType." ".$Name;
16989 }
16990 return $Name;
16991}
16992
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016993sub get_Anchor($$$)
16994{
16995 my ($Kind, $Level, $Severity) = @_;
16996 if($JoinReport)
16997 {
16998 if($Severity eq "Safe") {
16999 return "Other_".$Level."_Changes_In_".$Kind."s";
17000 }
17001 else {
17002 return $Kind."_".$Level."_Problems_".$Severity;
17003 }
17004 }
17005 else
17006 {
17007 if($Severity eq "Safe") {
17008 return "Other_Changes_In_".$Kind."s";
17009 }
17010 else {
17011 return $Kind."_Problems_".$Severity;
17012 }
17013 }
17014}
17015
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017016sub showVTables($)
17017{
17018 my $TypeName = $_[0];
17019 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017020 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017021 if(defined $Type1{"VTable"}
17022 and keys(%{$Type1{"VTable"}}))
17023 {
17024 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017025 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017026 if(defined $Type2{"VTable"}
17027 and keys(%{$Type2{"VTable"}}))
17028 {
17029 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17030 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017031 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017032 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017033 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17034 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017035 }
17036 my $VTABLES = "";
17037 if($ReportFormat eq "xml")
17038 { # XML
17039 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017040 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017041 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017042 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017043 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17044 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017045 $VTABLES .= " </entry>\n";
17046 }
17047 $VTABLES .= " </vtable>\n\n";
17048 }
17049 else
17050 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017051 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017052 $VTABLES .= "<tr><th width='2%'>Offset</th>";
17053 $VTABLES .= "<th width='45%'>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
17054 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017055 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017056 {
17057 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017058 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017059 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017060 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017061 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017062 $Color1 = " class='failed'";
17063 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017064 }
17065 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017066 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017067 }
17068 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017069 $VTABLES .= "<tr><th>".$Index."</th>\n";
17070 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17071 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017072 }
17073 $VTABLES .= "</table><br/>\n";
17074 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017075 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017076 }
17077 return $VTABLES;
17078 }
17079 }
17080 return "";
17081}
17082
17083sub simpleVEntry($)
17084{
17085 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017086 if(not defined $VEntry
17087 or $VEntry eq "") {
17088 return "";
17089 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017090 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17091 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17092 if($VEntry=~/\A_ZThn.+\Z/) {
17093 $VEntry = "non-virtual thunk";
17094 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017095 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017096 # support for old GCC versions
17097 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17098 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17099 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017100 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17101 return $VEntry;
17102}
17103
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017104sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017105{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017106 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017107 my $LIMIT = 1000;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017108 if($#{$Syms}>=10000)
17109 { # reduce size of the report
17110 $LIMIT = 10;
17111 }
17112 my %SProblems = ();
17113 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017114 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017115 if(keys(%SProblems)>$LIMIT) {
17116 last;
17117 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017118 if(($Symbol=~/C2E|D2E|D0E/))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017119 { # duplicated problems for C2 constructors, D2 and D0 destructors
17120 next;
17121 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017122 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17123 if($Level eq "Source")
17124 { # remove symbol version
17125 $Symbol=$SN;
17126 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017127 my ($MinPath_Length, $ProblemLocation_Last) = (-1, "");
17128 my $Severity_Max = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017129 my $Signature = get_Signature($Symbol, 1);
17130 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017131 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017132 foreach my $Location (keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017133 {
17134 if(not defined $Kinds_Locations->{$Kind}
17135 or not $Kinds_Locations->{$Kind}{$Location}) {
17136 next;
17137 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017138 if($SV and defined $CompatProblems{$Level}{$SN}
17139 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Location})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017140 { # duplicated problems for versioned symbols
17141 next;
17142 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017143 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017144 next if($Type_Name ne $Target_TypeName);
17145
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017146 my $Position = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Pos"};
17147 my $Param_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017148 my $Severity = getProblemSeverity($Level, $Kind);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017149 my $Path_Length = 0;
17150 my $ProblemLocation = $Location;
17151 if($Type_Name) {
17152 $ProblemLocation=~s/->\Q$Type_Name\E\Z//g;
17153 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017154 while($ProblemLocation=~/\-\>/g) {
17155 $Path_Length += 1;
17156 }
17157 if($MinPath_Length==-1 or ($Path_Length<=$MinPath_Length and $Severity_Val{$Severity}>$Severity_Max)
17158 or (cmp_locations($ProblemLocation, $ProblemLocation_Last) and $Severity_Val{$Severity}==$Severity_Max))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017159 {
17160 $MinPath_Length = $Path_Length;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017161 $Severity_Max = $Severity_Val{$Severity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017162 $ProblemLocation_Last = $ProblemLocation;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017163 %{$SProblems{$Symbol}} = (
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017164 "Descr"=>getAffectDescription($Level, $Symbol, $Kind, $Location),
17165 "Severity_Max"=>$Severity_Max,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017166 "Signature"=>$Signature,
17167 "Position"=>$Position,
17168 "Param_Name"=>$Param_Name,
17169 "Location"=>$Location
17170 );
17171 }
17172 }
17173 }
17174 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017175 my @Symbols = keys(%SProblems);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017176 @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 +040017177 @Symbols = sort {$SProblems{$b}{"Severity_Max"}<=>$SProblems{$a}{"Severity_Max"}} @Symbols;
17178 if($#Symbols+1>$LIMIT)
17179 { # remove last element
17180 pop(@Symbols);
17181 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017182 my $Affected = "";
17183 if($ReportFormat eq "xml")
17184 { # XML
17185 $Affected .= " <affected>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017186 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017187 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017188 my $Param_Name = $SProblems{$Symbol}{"Param_Name"};
17189 my $Description = $SProblems{$Symbol}{"Descr"};
17190 my $Location = $SProblems{$Symbol}{"Location"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017191 my $Target = "";
17192 if($Param_Name) {
17193 $Target = " affected=\"param\" param_name=\"$Param_Name\"";
17194 }
17195 elsif($Location=~/\Aretval(\-|\Z)/i) {
17196 $Target = " affected=\"retval\"";
17197 }
17198 elsif($Location=~/\Athis(\-|\Z)/i) {
17199 $Target = " affected=\"this\"";
17200 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017201 $Affected .= " <symbol$Target name=\"$Symbol\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017202 $Affected .= " <comment>".xmlSpecChars($Description)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017203 $Affected .= " </symbol>\n";
17204 }
17205 $Affected .= " </affected>\n";
17206 }
17207 else
17208 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017209 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017210 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017211 my $Description = $SProblems{$Symbol}{"Descr"};
17212 my $Signature = $SProblems{$Symbol}{"Signature"};
17213 my $Pos = $SProblems{$Symbol}{"Position"};
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017214 $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 +040017215 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017216 if(keys(%SProblems)>$LIMIT) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017217 $Affected .= "and others ...<br/>";
17218 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017219 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017220 if($Affected)
17221 {
17222 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017223 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".(keys(%SProblems)>$LIMIT?">".$LIMIT:keys(%SProblems)).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017224 }
17225 }
17226 return $Affected;
17227}
17228
17229sub cmp_locations($$)
17230{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017231 my ($L1, $L2) = @_;
17232 if($L2=~/\b(retval|this)\b/
17233 and $L1!~/\b(retval|this)\b/ and $L1!~/\-\>/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017234 return 1;
17235 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017236 if($L2=~/\b(retval|this)\b/ and $L2=~/\-\>/
17237 and $L1!~/\b(retval|this)\b/ and $L1=~/\-\>/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017238 return 1;
17239 }
17240 return 0;
17241}
17242
17243sub getAffectDescription($$$$)
17244{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017245 my ($Level, $Symbol, $Kind, $Location) = @_;
17246 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017247 my $PPos = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017248 my @Sentence = ();
17249 $Location=~s/\A(.*)\-\>.+?\Z/$1/;
17250 if($Kind eq "Overridden_Virtual_Method"
17251 or $Kind eq "Overridden_Virtual_Method_B") {
17252 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17253 }
17254 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17255 {
17256 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17257 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017258 my $METHOD_TYPE = $CompleteSignature{1}{$Symbol}{"Constructor"}?"constructor":"method";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017259 my $ClassName = $TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017260 if($ClassName eq $Problem{"Type_Name"}) {
17261 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17262 }
17263 else {
17264 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17265 }
17266 }
17267 else
17268 {
17269 if($Location=~/retval/)
17270 { # return value
17271 if($Location=~/\-\>/) {
17272 push(@Sentence, "Field \'".$Location."\' in return value");
17273 }
17274 else {
17275 push(@Sentence, "Return value");
17276 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017277 if(my $Init = $Problem{"InitialType_Type"})
17278 {
17279 if($Init eq "Pointer") {
17280 push(@Sentence, "(pointer)");
17281 }
17282 elsif($Init eq "Ref") {
17283 push(@Sentence, "(reference)");
17284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017285 }
17286 }
17287 elsif($Location=~/this/)
17288 { # "this" pointer
17289 if($Location=~/\-\>/) {
17290 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17291 }
17292 else {
17293 push(@Sentence, "\'this\' pointer");
17294 }
17295 }
17296 else
17297 { # parameters
17298 if($Location=~/\-\>/) {
17299 push(@Sentence, "Field \'".$Location."\' in $PPos parameter");
17300 }
17301 else {
17302 push(@Sentence, "$PPos parameter");
17303 }
17304 if($Problem{"Param_Name"}) {
17305 push(@Sentence, "\'".$Problem{"Param_Name"}."\'");
17306 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017307 if(my $Init = $Problem{"InitialType_Type"})
17308 {
17309 if($Init eq "Pointer") {
17310 push(@Sentence, "(pointer)");
17311 }
17312 elsif($Init eq "Ref") {
17313 push(@Sentence, "(reference)");
17314 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017315 }
17316 }
17317 if($Location eq "this") {
17318 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17319 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017320 elsif(defined $Problem{"Start_Type_Name"}
17321 and $Problem{"Start_Type_Name"} eq $Problem{"Type_Name"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017322 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17323 }
17324 else {
17325 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17326 }
17327 }
17328 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017329 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017330 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 +040017331 }
17332 return join(" ", @Sentence);
17333}
17334
17335sub get_XmlSign($$)
17336{
17337 my ($Symbol, $LibVersion) = @_;
17338 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17339 my $Report = "";
17340 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17341 {
17342 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017343 my $Type = $Info->{"Param"}{$Pos}{"type"};
17344 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017345 foreach my $Typedef (keys(%ChangedTypedef))
17346 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017347 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17348 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17349 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017350 }
17351 $Report .= " <param pos=\"$Pos\">\n";
17352 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017353 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017354 $Report .= " </param>\n";
17355 }
17356 if(my $Return = $Info->{"Return"})
17357 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017358 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017359 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017360 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017361 $Report .= " </retval>\n";
17362 }
17363 return $Report;
17364}
17365
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017366sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017367{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017368 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017369 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017370 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017371 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017372 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17373 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017374 next;
17375 }
17376 $Report .= " <symbol name=\"$Symbol\">\n";
17377 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017378 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017379 {
17380 if(defined $CompleteSignature{1}{$Symbol}
17381 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17382 {
17383 $P1 = get_XmlSign($Symbol, 1);
17384 $S1 = get_Signature($Symbol, 1);
17385 }
17386 elsif($Symbol=~/\A(_Z|\?)/) {
17387 $S1 = $tr_name{$Symbol};
17388 }
17389 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017390 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017391 {
17392 if(defined $CompleteSignature{2}{$Symbol}
17393 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17394 {
17395 $P2 = get_XmlSign($Symbol, 2);
17396 $S2 = get_Signature($Symbol, 2);
17397 }
17398 elsif($Symbol=~/\A(_Z|\?)/) {
17399 $S2 = $tr_name{$Symbol};
17400 }
17401 }
17402 if($S1)
17403 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017404 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017405 $Report .= $P1;
17406 $Report .= " </old>\n";
17407 }
17408 if($S2 and $S2 ne $S1)
17409 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017410 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017411 $Report .= $P2;
17412 $Report .= " </new>\n";
17413 }
17414 $Report .= " </symbol>\n";
17415 }
17416 $Report .= "</symbols_info>\n";
17417 return $Report;
17418}
17419
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017420sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017421{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017422 my ($Level, $Report) = @_;
17423 if($ReportFormat eq "xml") {
17424 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017425 }
17426 if($StdOut)
17427 { # --stdout option
17428 print STDOUT $Report;
17429 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017430 else
17431 {
17432 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017433 mkpath(get_dirname($RPath));
17434
17435 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17436 print REPORT $Report;
17437 close(REPORT);
17438
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017439 if($Browse or $OpenReport)
17440 { # open in browser
17441 openReport($RPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017442 if($JoinReport or $DoubleReport)
17443 {
17444 if($Level eq "Binary")
17445 { # wait to open a browser
17446 sleep(1);
17447 }
17448 }
17449 }
17450 }
17451}
17452
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017453sub openReport($)
17454{
17455 my $Path = $_[0];
17456 my $Cmd = "";
17457 if($Browse)
17458 { # user-defined browser
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017459 $Cmd = $Browse." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017460 }
17461 if(not $Cmd)
17462 { # default browser
17463 if($OSgroup eq "macos") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017464 $Cmd = "open \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017465 }
17466 elsif($OSgroup eq "windows") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017467 $Cmd = "start ".path_format($Path, $OSgroup);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017468 }
17469 else
17470 { # linux, freebsd, solaris
17471 my @Browsers = (
17472 "x-www-browser",
17473 "sensible-browser",
17474 "firefox",
17475 "opera",
17476 "xdg-open",
17477 "lynx",
17478 "links"
17479 );
17480 foreach my $Br (@Browsers)
17481 {
17482 if($Br = get_CmdPath($Br))
17483 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017484 $Cmd = $Br." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017485 last;
17486 }
17487 }
17488 }
17489 }
17490 if($Cmd)
17491 {
17492 if($Debug) {
17493 printMsg("INFO", "running $Cmd");
17494 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017495 if($OSgroup ne "windows"
17496 and $OSgroup ne "macos")
17497 {
17498 if($Cmd!~/lynx|links/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017499 $Cmd .= " >\"/dev/null\" 2>&1 &";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017500 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017501 }
17502 system($Cmd);
17503 }
17504 else {
17505 printMsg("ERROR", "cannot open report in browser");
17506 }
17507}
17508
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017509sub getReport($)
17510{
17511 my $Level = $_[0];
17512 if($ReportFormat eq "xml")
17513 { # XML
17514
17515 if($Level eq "Join")
17516 {
17517 my $Report = "<reports>\n";
17518 $Report .= getReport("Binary");
17519 $Report .= getReport("Source");
17520 $Report .= "</reports>\n";
17521 return $Report;
17522 }
17523 else
17524 {
17525 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17526 my ($Summary, $MetaData) = get_Summary($Level);
17527 $Report .= $Summary."\n";
17528 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17529 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17530 $Report .= get_Report_SymbolsInfo($Level);
17531 $Report .= "</report>\n";
17532 return $Report;
17533 }
17534 }
17535 else
17536 { # HTML
17537 my $CssStyles = readModule("Styles", "Report.css");
17538 my $JScripts = readModule("Scripts", "Sections.js");
17539 if($Level eq "Join")
17540 {
17541 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17542 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017543 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
17544 my $Keywords = $TargetLibraryFName.", compatibility, API, report";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017545 my $Description = "Compatibility report for the $TargetLibraryFName $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
17546 my ($BSummary, $BMetaData) = get_Summary("Binary");
17547 my ($SSummary, $SMetaData) = get_Summary("Source");
17548 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>";
17549 $Report .= get_Report_Header("Join")."
17550 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017551 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17552 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017553 </div>";
17554 $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>";
17555 $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 +040017556 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017557 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17558 return $Report;
17559 }
17560 else
17561 {
17562 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017563 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17564 my $Keywords = $TargetLibraryFName.", ".lc($Level)." compatibility, API, report";
17565 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 +040017566 if($Level eq "Binary")
17567 {
17568 if(getArch(1) eq getArch(2)
17569 and getArch(1) ne "unknown") {
17570 $Description .= " on ".showArch(getArch(1));
17571 }
17572 }
17573 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."\n<body>\n<div><a name='Top'></a>\n";
17574 $Report .= get_Report_Header($Level)."\n".$Summary."\n";
17575 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17576 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17577 $Report .= get_SourceInfo();
17578 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017579 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017580 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17581 return $Report;
17582 }
17583 }
17584}
17585
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017586sub getLegend()
17587{
17588 return "<br/>
17589<table class='summary'>
17590<tr>
17591 <td class='new'>added</td>
17592 <td class='passed'>compatible</td>
17593</tr>
17594<tr>
17595 <td class='warning'>warning</td>
17596 <td class='failed'>incompatible</td>
17597</tr></table>\n";
17598}
17599
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017600sub createReport()
17601{
17602 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017603 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017604 writeReport("Join", getReport("Join"));
17605 }
17606 elsif($DoubleReport)
17607 { # default
17608 writeReport("Binary", getReport("Binary"));
17609 writeReport("Source", getReport("Source"));
17610 }
17611 elsif($BinaryOnly)
17612 { # --binary
17613 writeReport("Binary", getReport("Binary"));
17614 }
17615 elsif($SourceOnly)
17616 { # --source
17617 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017618 }
17619}
17620
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017621sub getReportFooter($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017622{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017623 my ($LibName, $Wide) = @_;
17624 my $FooterStyle = $Wide?"width:99%":"width:97%;padding-top:3px";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017625 my $Footer = "<div style='$FooterStyle;font-size:11px;' align='right'><i>Generated on ".(localtime time); # report date
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017626 $Footer .= " for <span style='font-weight:bold'>$LibName</span>"; # tested library/system name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017627 $Footer .= " by <a href='".$HomePage{"Wiki"}."'>ABI Compliance Checker</a>"; # tool name
17628 my $ToolSummary = "<br/>A tool for checking backward compatibility of a C/C++ library API&#160;&#160;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017629 $Footer .= " $TOOL_VERSION &#160;$ToolSummary</i></div>"; # tool version
17630 return $Footer;
17631}
17632
17633sub get_Report_Problems($$)
17634{
17635 my ($Priority, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017636 my $Report = get_Report_TypeProblems($Priority, $Level);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017637 if(my $SProblems = get_Report_SymbolProblems($Priority, $Level)) {
17638 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017639 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017640 if($Priority eq "Low")
17641 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017642 $Report .= get_Report_ChangedConstants("Low", $Level);
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +040017643 if($ReportFormat eq "html")
17644 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017645 if($CheckImpl and $Level eq "Binary") {
17646 $Report .= get_Report_Impl();
17647 }
17648 }
17649 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017650 if($Priority eq "Safe")
17651 {
17652 $Report .= get_Report_ChangedConstants("Safe", $Level);
17653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017654 if($ReportFormat eq "html")
17655 {
17656 if($Report)
17657 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017658 if($JoinReport)
17659 {
17660 if($Priority eq "Safe") {
17661 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17662 }
17663 else {
17664 $Report = "<a name=\'".$Priority."_Risk_".$Level."_Problems\'></a>".$Report;
17665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017666 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017667 else
17668 {
17669 if($Priority eq "Safe") {
17670 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17671 }
17672 else {
17673 $Report = "<a name=\'".$Priority."_Risk_Problems\'></a>".$Report;
17674 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017675 }
17676 }
17677 }
17678 return $Report;
17679}
17680
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017681sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017682{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017683 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17684 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17685 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17686 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017687 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17688 <meta name=\"keywords\" content=\"$Keywords\" />
17689 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017690 <title>
17691 $Title
17692 </title>
17693 <style type=\"text/css\">
17694 $Styles
17695 </style>
17696 <script type=\"text/javascript\" language=\"JavaScript\">
17697 <!--
17698 $Scripts
17699 -->
17700 </script>
17701 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017702}
17703
17704sub insertIDs($)
17705{
17706 my $Text = $_[0];
17707 while($Text=~/CONTENT_ID/)
17708 {
17709 if(int($Content_Counter)%2) {
17710 $ContentID -= 1;
17711 }
17712 $Text=~s/CONTENT_ID/c_$ContentID/;
17713 $ContentID += 1;
17714 $Content_Counter += 1;
17715 }
17716 return $Text;
17717}
17718
17719sub checkPreprocessedUnit($)
17720{
17721 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017722 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017723 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017724 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017725
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017726 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017727 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017728 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017729 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017730 chomp($Line);
17731 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017732 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017733 $CurHeader = path_format($1, $OSgroup);
17734 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017735 $CurClass = "";
17736
17737 if(index($CurHeader, $TMP_DIR)==0) {
17738 next;
17739 }
17740
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017741 if(substr($CurHeaderName, 0, 1) eq "<")
17742 { # <built-in>, <command-line>, etc.
17743 $CurHeaderName = "";
17744 $CurHeader = "";
17745 }
17746
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017747 if($ExtraInfo)
17748 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017749 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017750 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17751 }
17752 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017753 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017754 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017755 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017756 if($CurHeaderName)
17757 {
17758 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17759 and not $Registered_Headers{$Version}{$CurHeader})
17760 { # not a target
17761 next;
17762 }
17763 if(not is_target_header($CurHeaderName, 1)
17764 and not is_target_header($CurHeaderName, 2))
17765 { # user-defined header
17766 next;
17767 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017768 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017769 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017770
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017771 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017772 {
17773 my ($Name, $Value) = ($1, $2);
17774 if(not $Constants{$Version}{$Name}{"Access"})
17775 {
17776 $Constants{$Version}{$Name}{"Access"} = "public";
17777 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017778 if($CurHeaderName) {
17779 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17780 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017781 }
17782 }
17783 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17784 $Constants{$Version}{$1}{"Access"} = "private";
17785 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017786 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017787 else
17788 {
17789 if(defined $ExtraDump)
17790 {
17791 if($Line=~/(\w+)\s*\(/)
17792 { # functions
17793 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17794 }
17795 #elsif($Line=~/(\w+)\s*;/)
17796 #{ # data
17797 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17798 #}
17799 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17800 $CurClass = $2;
17801 }
17802 }
17803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017804 }
17805 close(PREPROC);
17806 foreach my $Constant (keys(%{$Constants{$Version}}))
17807 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017808 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17809 {
17810 delete($Constants{$Version}{$Constant});
17811 next;
17812 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017813 if(not $ExtraDump and ($Constant=~/_h\Z/i
17814 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017815 { # skip
17816 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017817 }
17818 else {
17819 delete($Constants{$Version}{$Constant}{"Access"});
17820 }
17821 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017822 if($Debug)
17823 {
17824 mkpath($DEBUG_PATH{$Version});
17825 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017827}
17828
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017829sub uncoverConstant($$)
17830{
17831 my ($LibVersion, $Constant) = @_;
17832 return "" if(not $LibVersion or not $Constant);
17833 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17834 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17835 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17836 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017837
17838 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017839 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017840 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17841 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017842 {
17843 push(@RecurConstant, $Constant);
17844 my $Uncovered = uncoverConstant($LibVersion, $Value);
17845 if($Uncovered ne "") {
17846 $Value = $Uncovered;
17847 }
17848 pop(@RecurConstant);
17849 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017850
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017851 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017852 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017853 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17854 }
17855 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17856}
17857
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017858sub simpleConstant($$)
17859{
17860 my ($LibVersion, $Value) = @_;
17861 if($Value=~/\W/)
17862 {
17863 my $Value_Copy = $Value;
17864 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17865 {
17866 my $Word = $1;
17867 if($Value!~/$Word\s*\(/)
17868 {
17869 my $Val = uncoverConstant($LibVersion, $Word);
17870 if($Val ne "")
17871 {
17872 $Value=~s/\b$Word\b/$Val/g;
17873 }
17874 }
17875 }
17876 }
17877 return $Value;
17878}
17879
17880sub computeValue($)
17881{
17882 my $Value = $_[0];
17883
17884 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17885 return $1;
17886 }
17887
17888 if($Value=~/\A[\d\-\+()]+\Z/) {
17889 return eval($Value);
17890 }
17891
17892 return $Value;
17893}
17894
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017895my %IgnoreConstant = map {$_=>1} (
17896 "VERSION",
17897 "VERSIONCODE",
17898 "VERNUM",
17899 "VERS_INFO",
17900 "PATCHLEVEL",
17901 "INSTALLPREFIX",
17902 "VBUILD",
17903 "VPATCH",
17904 "VMINOR",
17905 "BUILD_STRING",
17906 "BUILD_TIME",
17907 "PACKAGE_STRING",
17908 "PRODUCTION",
17909 "CONFIGURE_COMMAND",
17910 "INSTALLDIR",
17911 "BINDIR",
17912 "CONFIG_FILE_PATH",
17913 "DATADIR",
17914 "EXTENSION_DIR",
17915 "INCLUDE_PATH",
17916 "LIBDIR",
17917 "LOCALSTATEDIR",
17918 "SBINDIR",
17919 "SYSCONFDIR",
17920 "RELEASE",
17921 "SOURCE_ID",
17922 "SUBMINOR",
17923 "MINOR",
17924 "MINNOR",
17925 "MINORVERSION",
17926 "MAJOR",
17927 "MAJORVERSION",
17928 "MICRO",
17929 "MICROVERSION",
17930 "BINARY_AGE",
17931 "INTERFACE_AGE",
17932 "CORE_ABI",
17933 "PATCH",
17934 "COPYRIGHT",
17935 "TIMESTAMP",
17936 "REVISION",
17937 "PACKAGE_TAG",
17938 "PACKAGEDATE",
17939 "NUMVERSION",
17940 "Release",
17941 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017942);
17943
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017944sub constantFilter($$$)
17945{
17946 my ($Name, $Value, $Level) = @_;
17947
17948 if($Level eq "Binary")
17949 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017950 if($Name=~/_t\Z/)
17951 { # __malloc_ptr_t
17952 return 1;
17953 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017954 foreach (keys(%IgnoreConstant))
17955 {
17956 if($Name=~/(\A|_)$_(_|\Z)/)
17957 { # version
17958 return 1;
17959 }
17960 if(/\A[A-Z].*[a-z]\Z/)
17961 {
17962 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17963 { # version
17964 return 1;
17965 }
17966 }
17967 }
17968 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17969 { # version
17970 return 1;
17971 }
17972 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17973 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17974 return 1;
17975 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017976
17977 if($Value=~/\A["'].*['"]/i)
17978 { # string
17979 return 0;
17980 }
17981
17982 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17983 { # static int gcry_pth_init
17984 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017985 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017986 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017987 return 1;
17988 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017989 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017990 { # foo(p)
17991 return 1;
17992 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017993 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017994 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017995 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017996 return 1;
17997 }
17998 }
17999
18000 return 0;
18001}
18002
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018003sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018004{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018005 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018006 foreach my $Constant (keys(%{$Constants{1}}))
18007 {
18008 if($SkipConstants{1}{$Constant})
18009 { # skipped by the user
18010 next;
18011 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018012
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018013 if(my $Header = $Constants{1}{$Constant}{"Header"})
18014 {
18015 if(not is_target_header($Header, 1)
18016 and not is_target_header($Header, 2))
18017 { # user-defined header
18018 next;
18019 }
18020 }
18021 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018022 next;
18023 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018024
18025 my $Old_Value = uncoverConstant(1, $Constant);
18026
18027 if(constantFilter($Constant, $Old_Value, $Level))
18028 { # separate binary and source problems
18029 next;
18030 }
18031
18032 if(not defined $Constants{2}{$Constant}{"Value"})
18033 { # removed
18034 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18035 "Target"=>$Constant,
18036 "Old_Value"=>$Old_Value );
18037 next;
18038 }
18039
18040 if($Constants{2}{$Constant}{"Value"} eq "")
18041 { # empty value
18042 # TODO: implement a rule
18043 next;
18044 }
18045
18046 my $New_Value = uncoverConstant(2, $Constant);
18047
18048 my $Old_Value_Pure = $Old_Value;
18049 my $New_Value_Pure = $New_Value;
18050
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018051 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18052 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18053 $New_Value_Pure=~s/(\W)\s+/$1/g;
18054 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018055
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018056 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018057
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018058 if($New_Value_Pure ne $Old_Value_Pure)
18059 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018060 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18061 { # complex values
18062 next;
18063 }
18064 if(computeValue($Old_Value) eq computeValue($New_Value))
18065 { # expressions
18066 next;
18067 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018068 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18069 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18070 next;
18071 }
18072 if($Old_Value eq "0" and $New_Value eq "NULL")
18073 { # 0 => NULL
18074 next;
18075 }
18076 if($Old_Value eq "NULL" and $New_Value eq "0")
18077 { # NULL => 0
18078 next;
18079 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018080 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018081 "Target"=>$Constant,
18082 "Old_Value"=>$Old_Value,
18083 "New_Value"=>$New_Value );
18084 }
18085 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018086
18087 foreach my $Constant (keys(%{$Constants{2}}))
18088 {
18089 if(not defined $Constants{1}{$Constant}{"Value"})
18090 {
18091 if($SkipConstants{2}{$Constant})
18092 { # skipped by the user
18093 next;
18094 }
18095
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018096 if(my $Header = $Constants{2}{$Constant}{"Header"})
18097 {
18098 if(not is_target_header($Header, 1)
18099 and not is_target_header($Header, 2))
18100 { # user-defined header
18101 next;
18102 }
18103 }
18104 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018105 next;
18106 }
18107
18108 my $New_Value = uncoverConstant(2, $Constant);
18109 if(not defined $New_Value or $New_Value eq "") {
18110 next;
18111 }
18112
18113 if(constantFilter($Constant, $New_Value, $Level))
18114 { # separate binary and source problems
18115 next;
18116 }
18117
18118 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18119 "Target"=>$Constant,
18120 "New_Value"=>$New_Value );
18121 }
18122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018123}
18124
18125sub convert_integer($)
18126{
18127 my $Value = $_[0];
18128 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018129 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018130 return hex($Value);
18131 }
18132 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018133 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018134 return oct($Value);
18135 }
18136 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018137 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018138 return oct($Value);
18139 }
18140 else {
18141 return $Value;
18142 }
18143}
18144
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018145sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018146{
18147 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018148 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018149 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018150 {
18151 if($LibVersion==1)
18152 {
18153 printMsg("WARNING", "checking headers only");
18154 $CheckHeadersOnly = 1;
18155 }
18156 else {
18157 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18158 }
18159 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018160
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018161 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018162 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018163 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018164
18165 if($CheckUndefined)
18166 {
18167 my %UndefinedLibs = ();
18168
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018169 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18170
18171 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018172 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018173 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018174 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018175 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018176 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018177 if($Symbol_Library{$LibVersion}{$Symbol}
18178 or $DepSymbol_Library{$LibVersion}{$Symbol})
18179 { # exported by target library
18180 next;
18181 }
18182 if(index($Symbol, '@')!=-1)
18183 { # exported default symbol version (@@)
18184 $Symbol=~s/\@/\@\@/;
18185 if($Symbol_Library{$LibVersion}{$Symbol}
18186 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18187 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018188 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018189 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018190 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18191 $UndefinedLibs{$Path} = 1;
18192 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018193 }
18194 }
18195 }
18196 if($ExtraInfo)
18197 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018198 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018199 {
18200 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018201 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018202 foreach (@Paths)
18203 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018204 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018205 my ($Dir, $Name) = separate_path($_);
18206
18207 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018208 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018209 }
18210
18211 $Name = parse_libname($Name, "name", $OStarget);
18212 $Name=~s/\Alib//;
18213
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018214 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018215 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018216
18217 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18218 {
18219 $LibString = " -L".esc($Dir).$LibString;
18220 }
18221
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018222 writeFile($ExtraInfo."/libs-string", $LibString);
18223 }
18224 }
18225 }
18226
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018227 if($ExtraInfo) {
18228 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18229 }
18230
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018231 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018232 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018233 if($#LibPaths!=-1)
18234 {
18235 if(not keys(%{$Symbol_Library{$LibVersion}}))
18236 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018237 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018238 printMsg("WARNING", "checking headers only");
18239 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018240 }
18241 }
18242 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018243
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018244 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018245 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018246}
18247
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018248my %Prefix_Lib_Map=(
18249 # symbols for autodetecting library dependencies (by prefix)
18250 "pthread_" => ["libpthread"],
18251 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18252 "cairo_" => ["libcairo"],
18253 "gtk_" => ["libgtk-x11-2.0"],
18254 "atk_" => ["libatk-1.0"],
18255 "gdk_" => ["libgdk-x11-2.0"],
18256 "gl" => ["libGL"],
18257 "glu" => ["libGLU"],
18258 "popt" => ["libpopt"],
18259 "Py" => ["libpython"],
18260 "jpeg_" => ["libjpeg"],
18261 "BZ2_" => ["libbz2"],
18262 "Fc" => ["libfontconfig"],
18263 "Xft" => ["libXft"],
18264 "SSL_" => ["libssl"],
18265 "sem_" => ["libpthread"],
18266 "snd_" => ["libasound"],
18267 "art_" => ["libart_lgpl_2"],
18268 "dbus_g" => ["libdbus-glib-1"],
18269 "GOMP_" => ["libgomp"],
18270 "omp_" => ["libgomp"],
18271 "cms" => ["liblcms"]
18272);
18273
18274my %Pattern_Lib_Map=(
18275 "SL[a-z]" => ["libslang"]
18276);
18277
18278my %Symbol_Lib_Map=(
18279 # symbols for autodetecting library dependencies (by name)
18280 "pow" => "libm",
18281 "fmod" => "libm",
18282 "sin" => "libm",
18283 "floor" => "libm",
18284 "cos" => "libm",
18285 "dlopen" => "libdl",
18286 "deflate" => "libz",
18287 "inflate" => "libz",
18288 "move_panel" => "libpanel",
18289 "XOpenDisplay" => "libX11",
18290 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018291 "clock_gettime" => "librt",
18292 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018293);
18294
18295sub find_SymbolLibs($$)
18296{
18297 my ($LibVersion, $Symbol) = @_;
18298
18299 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18300 { # debug symbols
18301 return ();
18302 }
18303
18304 my %Paths = ();
18305
18306 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18307 {
18308 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18309 $Paths{$Path} = 1;
18310 }
18311 }
18312
18313 if(my $SymbolPrefix = getPrefix($Symbol))
18314 {
18315 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18316 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18317 }
18318
18319 if(not keys(%Paths))
18320 {
18321 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18322 {
18323 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18324 {
18325 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18326 $Paths{$Path} = 1;
18327 }
18328 }
18329 }
18330 }
18331
18332 if(not keys(%Paths))
18333 {
18334 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18335 {
18336 if($Symbol=~/\A$Prefix/)
18337 {
18338 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18339 {
18340 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18341 $Paths{$Path} = 1;
18342 }
18343 }
18344 }
18345 }
18346 }
18347
18348 if(not keys(%Paths))
18349 {
18350 if($SymbolPrefix)
18351 { # try to find a library by symbol prefix
18352 if($SymbolPrefix eq "inotify" and
18353 index($Symbol, "\@GLIBC")!=-1)
18354 {
18355 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18356 $Paths{$Path} = 1;
18357 }
18358 }
18359 else
18360 {
18361 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18362 $Paths{$Path} = 1;
18363 }
18364 }
18365 }
18366 }
18367
18368 if(my @Paths = keys(%Paths)) {
18369 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18370 }
18371 }
18372 return keys(%Paths);
18373}
18374
18375sub get_LibPath_Prefix($$)
18376{
18377 my ($LibVersion, $Prefix) = @_;
18378
18379 $Prefix = lc($Prefix);
18380 $Prefix=~s/[_]+\Z//g;
18381
18382 foreach ("-2", "2", "-1", "1", "")
18383 { # libgnome-2.so
18384 # libxml2.so
18385 # libdbus-1.so
18386 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18387 return $Path;
18388 }
18389 }
18390 return "";
18391}
18392
18393sub getPrefix($)
18394{
18395 my $Str = $_[0];
18396 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18397 { # XmuValidArea: Xmu
18398 return $1;
18399 }
18400 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18401 { # snfReadFont: snf
18402 return $1;
18403 }
18404 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18405 { # XRRTimes: XRR
18406 return $1;
18407 }
18408 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18409 { # H5HF_delete: H5
18410 return $1;
18411 }
18412 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18413 { # alarm_event_add: alarm_
18414 return $1;
18415 }
18416 elsif($Str=~/\A(([a-z])\2{1,})/i)
18417 { # ffopen
18418 return $1;
18419 }
18420 return "";
18421}
18422
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018423sub getSymbolSize($$)
18424{ # size from the shared library
18425 my ($Symbol, $LibVersion) = @_;
18426 return 0 if(not $Symbol);
18427 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18428 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18429 {
18430 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18431 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18432 {
18433 if($Size<0) {
18434 return -$Size;
18435 }
18436 }
18437 }
18438 return 0;
18439}
18440
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018441sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018442{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18443 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018444 my ($Name, $Type) = @_;
18445
18446 # single
18447 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018448 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018449 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018450 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018451 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018452
18453 # double
18454 if($Name=~/$DEFAULT_STD_PARMS/)
18455 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018456 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018457 {
18458 my ($ShortName, $FuncParams) = split_Signature($Name);
18459
18460 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18461 {
18462 if(index($FParam, "<")!=-1)
18463 {
18464 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18465 my $FParam_N = canonifyName($FParam, "T");
18466 if($FParam_N ne $FParam) {
18467 $Name=~s/\Q$FParam\E/$FParam_N/g;
18468 }
18469 }
18470 }
18471 }
18472 elsif($Type eq "T")
18473 {
18474 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18475
18476 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018477 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018478 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018479 my $FParam = $TParams[0];
18480 foreach my $Pos (1 .. $#TParams)
18481 {
18482 my $TParam = $TParams[$Pos];
18483 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18484 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18485 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018486 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018487 }
18488 }
18489 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018490 if($Type eq "S") {
18491 return formatName($Name, "S");
18492 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018493 return $Name;
18494}
18495
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018496sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018497{
18498 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018499 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018500 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018501 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018502 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018503 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018504 next if($tr_name{$Symbol});
18505 $Symbol=~s/[\@\$]+(.*)\Z//;
18506 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018507 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018508 elsif(index($Symbol, "?")==0)
18509 {
18510 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018511 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018512 }
18513 else
18514 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018515 $tr_name{$Symbol} = $Symbol;
18516 $mangled_name_gcc{$Symbol} = $Symbol;
18517 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018518 }
18519 }
18520 if($#MnglNames1 > -1)
18521 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018522 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018523 foreach my $MnglName (@MnglNames1)
18524 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018525 if(my $Unmangled = pop(@UnmangledNames))
18526 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018527 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018528 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18529 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18530 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018531 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018532 and $tr_name{$MnglName}=~/vtable for (.+)/)
18533 { # bind class name and v-table symbol
18534 my $ClassName = $1;
18535 $ClassVTable{$ClassName} = $MnglName;
18536 $VTableClass{$MnglName} = $ClassName;
18537 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018538 }
18539 }
18540 }
18541 if($#MnglNames2 > -1)
18542 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018543 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018544 foreach my $MnglName (@MnglNames2)
18545 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018546 if(my $Unmangled = pop(@UnmangledNames))
18547 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018548 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018549 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18550 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018551 }
18552 }
18553 return \%tr_name;
18554}
18555
18556sub link_symbol($$$)
18557{
18558 my ($Symbol, $RunWith, $Deps) = @_;
18559 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18560 return 1;
18561 }
18562 if($Deps eq "+Deps")
18563 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018564 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018565 return 1;
18566 }
18567 }
18568 return 0;
18569}
18570
18571sub link_symbol_internal($$$)
18572{
18573 my ($Symbol, $RunWith, $Where) = @_;
18574 return 0 if(not $Where or not $Symbol);
18575 if($Where->{$RunWith}{$Symbol})
18576 { # the exact match by symbol name
18577 return 1;
18578 }
18579 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18580 { # indirect symbol version, i.e.
18581 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018582 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018583 if($Where->{$RunWith}{$VSym}) {
18584 return 1;
18585 }
18586 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018587 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018588 if($Sym and $Ver)
18589 { # search for the symbol with the same version
18590 # or without version
18591 if($Where->{$RunWith}{$Sym})
18592 { # old: foo@v|foo@@v
18593 # new: foo
18594 return 1;
18595 }
18596 if($Where->{$RunWith}{$Sym."\@".$Ver})
18597 { # old: foo|foo@@v
18598 # new: foo@v
18599 return 1;
18600 }
18601 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18602 { # old: foo|foo@v
18603 # new: foo@@v
18604 return 1;
18605 }
18606 }
18607 return 0;
18608}
18609
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018610sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018611{
18612 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018613 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018614 my @Imported = ();
18615 if($OSgroup eq "macos")
18616 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018617 my $NM = get_CmdPath("nm");
18618 if(not $NM) {
18619 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018620 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018621 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018622 while(<APP>)
18623 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018624 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018625 push(@Imported, $1);
18626 }
18627 }
18628 close(APP);
18629 }
18630 elsif($OSgroup eq "windows")
18631 {
18632 my $DumpBinCmd = get_CmdPath("dumpbin");
18633 if(not $DumpBinCmd) {
18634 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18635 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018636 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018637 while(<APP>)
18638 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018639 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18640 push(@Imported, $1);
18641 }
18642 }
18643 close(APP);
18644 }
18645 else
18646 {
18647 my $ReadelfCmd = get_CmdPath("readelf");
18648 if(not $ReadelfCmd) {
18649 exitStatus("Not_Found", "can't find \"readelf\"");
18650 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018651 open(APP, "$ReadelfCmd -WhlSsdA \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018652 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018653 while(<APP>)
18654 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018655 if(defined $symtab)
18656 { # do nothing with symtab
18657 if(index($_, "'.dynsym'")!=-1)
18658 { # dynamic table
18659 $symtab = undef;
18660 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018661 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018662 elsif(index($_, "'.symtab'")!=-1)
18663 { # symbol table
18664 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018665 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018666 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018667 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018668 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18669 if($Ndx eq "UND")
18670 { # only imported symbols
18671 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018672 }
18673 }
18674 }
18675 close(APP);
18676 }
18677 return @Imported;
18678}
18679
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018680my %ELF_BIND = map {$_=>1} (
18681 "WEAK",
18682 "GLOBAL"
18683);
18684
18685my %ELF_TYPE = map {$_=>1} (
18686 "FUNC",
18687 "IFUNC",
18688 "OBJECT",
18689 "COMMON"
18690);
18691
18692my %ELF_VIS = map {$_=>1} (
18693 "DEFAULT",
18694 "PROTECTED"
18695);
18696
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018697sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018698{ # read the line of 'readelf' output corresponding to the symbol
18699 my @Info = split(/\s+/, $_[0]);
18700 # Num: Value Size Type Bind Vis Ndx Name
18701 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018702 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018703 shift(@Info); # spaces
18704 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018705
18706 if($#Info==7)
18707 { # UND SYMBOL (N)
18708 if($Info[7]=~/\(\d+\)/) {
18709 pop(@Info);
18710 }
18711 }
18712
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018713 if($#Info!=6)
18714 { # other lines
18715 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018716 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018717 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018718 return () if(not defined $ELF_BIND{$Info[3]});
18719 return () if(not defined $ELF_VIS{$Info[4]});
18720 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18721 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18722 return ();
18723 }
18724 if($OStarget eq "symbian")
18725 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18726 if(index($Info[6], "_._.absent_export_")!=-1)
18727 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18728 return ();
18729 }
18730 $Info[6]=~s/\@.+//g; # remove version
18731 }
18732 if(index($Info[2], "0x") == 0)
18733 { # size == 0x3d158
18734 $Info[2] = hex($Info[2]);
18735 }
18736 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018737}
18738
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018739sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018740{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018741 my ($LibVersion, $Name) = @_;
18742 return "" if(not $LibVersion or not $Name);
18743 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18744 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018745 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018746 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18747}
18748
18749sub get_LibPath_I($$)
18750{
18751 my ($LibVersion, $Name) = @_;
18752 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018753 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018754 if(-f $Name)
18755 { # absolute path
18756 return $Name;
18757 }
18758 else
18759 { # broken
18760 return "";
18761 }
18762 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018763 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018764 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018765 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018766 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018767 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018768 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018769 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018770 }
18771 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18772 { # ldconfig default paths
18773 return $DefaultPath;
18774 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018775 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018776 { # search in default linker directories
18777 # and then in all system paths
18778 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018779 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018780 }
18781 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018782 if(not defined $Cache{"checkSystemFiles"}) {
18783 checkSystemFiles();
18784 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018785 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18786 return $AllObjects[0];
18787 }
18788 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18789 {
18790 if($ShortName ne $Name)
18791 { # FIXME: check this case
18792 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18793 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018794 }
18795 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018796 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018797 # can't find
18798 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018799}
18800
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018801sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018802{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018803 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18804 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018805
18806 my $Real_Path = realpath($Lib_Path);
18807
18808 if(not $Real_Path)
18809 { # broken link
18810 return ();
18811 }
18812
18813 my $Lib_Name = get_filename($Real_Path);
18814
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018815 if($ExtraInfo)
18816 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018817 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018818 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018819 }
18820
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018821 if($IsNeededLib)
18822 {
18823 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18824 return ();
18825 }
18826 }
18827 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018828 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018829
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018830 if($CheckImpl)
18831 {
18832 if(not $IsNeededLib) {
18833 getImplementations($LibVersion, $Lib_Path);
18834 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018835 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018836
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018837 push(@RecurLib, $Lib_Name);
18838 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018839 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18840
18841 if(not $IsNeededLib)
18842 { # special cases: libstdc++ and libc
18843 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18844 {
18845 if($ShortName eq "libstdc++")
18846 { # libstdc++.so.6
18847 $STDCXX_TESTING = 1;
18848 }
18849 elsif($ShortName eq "libc")
18850 { # libc-2.11.3.so
18851 $GLIBC_TESTING = 1;
18852 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018853 }
18854 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018855 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018856 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018857 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018858 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018859 mkpath(get_dirname($DebugPath));
18860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018861 if($OStarget eq "macos")
18862 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018863 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018864 if(not $NM) {
18865 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018866 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018867 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018868 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018869 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018870 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018871 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018872 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018873 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018874 else
18875 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018876 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018877 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018878 while(<LIB>)
18879 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018880 if($CheckUndefined)
18881 {
18882 if(not $IsNeededLib)
18883 {
18884 if(/ U _([\w\$]+)\s*\Z/)
18885 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018886 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018887 next;
18888 }
18889 }
18890 }
18891
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018892 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018893 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018894 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018895 if($IsNeededLib)
18896 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018897 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018898 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018899 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18900 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018901 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018902 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018903 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018904 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018905 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18906 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018907 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18908 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018909 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018910 setLanguage($LibVersion, "C++");
18911 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018912 }
18913 if($CheckObjectsOnly
18914 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018915 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018916 }
18917 }
18918 }
18919 }
18920 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018921
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018922 if($Deps)
18923 {
18924 if($LIB_TYPE eq "dynamic")
18925 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018926
18927 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018928 if(not $OtoolCmd) {
18929 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018930 }
18931
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018932 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18933 while(<LIB>)
18934 {
18935 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18936 and $1 ne $Lib_Path) {
18937 $NeededLib{$1} = 1;
18938 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018939 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018940 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018941 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018942 }
18943 }
18944 elsif($OStarget eq "windows")
18945 { # Windows *.dll, *.lib
18946 my $DumpBinCmd = get_CmdPath("dumpbin");
18947 if(not $DumpBinCmd) {
18948 exitStatus("Not_Found", "can't find \"dumpbin\"");
18949 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018950 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018951 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018952 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018953 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018954 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018955 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018956 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018957 else
18958 { # write to pipe
18959 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018961 while(<LIB>)
18962 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18963 # 1198 4AD SetThreadToken (forwarded to ...)
18964 # 3368 _o2i_ECPublicKey
18965 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*\Z/i
18966 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
18967 or /\A\s*\d+\s+_([\w\?\@]+)\s*\Z/)
18968 { # dynamic, static and forwarded symbols
18969 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018970 if($IsNeededLib)
18971 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018972 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018973 {
18974 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18975 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018977 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018978 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018979 {
18980 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18981 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018982 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18983 {
18984 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18985 setLanguage($LibVersion, "C++");
18986 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018987 }
18988 if($CheckObjectsOnly
18989 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018990 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018991 }
18992 }
18993 }
18994 }
18995 close(LIB);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018996 if($Deps)
18997 {
18998 if($LIB_TYPE eq "dynamic")
18999 { # dependencies
19000 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19001 while(<LIB>)
19002 {
19003 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19004 and $1 ne $Lib_Path) {
19005 $NeededLib{path_format($1, $OSgroup)} = 1;
19006 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019007 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019008 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019009 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019010 }
19011 }
19012 else
19013 { # Unix; *.so, *.a
19014 # Symbian: *.dso, *.lib
19015 my $ReadelfCmd = get_CmdPath("readelf");
19016 if(not $ReadelfCmd) {
19017 exitStatus("Not_Found", "can't find \"readelf\"");
19018 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019019 $ReadelfCmd .= " -WhlSsdA \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19020 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019021 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019022 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019023 system($ReadelfCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019024 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019025 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019026 else
19027 { # write to pipe
19028 open(LIB, $ReadelfCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019029 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019030 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019031 while(<LIB>)
19032 {
19033 if($LIB_TYPE eq "dynamic")
19034 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019035 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019036 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019037 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019038 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019039 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019040 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019041 # do nothing with symtab
19042 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019043 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019044 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019045 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019046 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019047 next;
19048 }
19049 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019050 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019051 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019052 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019053 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019054 if($CheckUndefined)
19055 {
19056 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019057 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019058 }
19059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019060 next;
19061 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019062 if($Bind eq "WEAK")
19063 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019064 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019065 if($Weak eq "-Weak")
19066 { # skip WEAK symbols
19067 next;
19068 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019069 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019070 my $Short = $Symbol;
19071 $Short=~s/\@.+//g;
19072 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019073 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019074 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19075 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019076 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019077 if($IsNeededLib)
19078 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019079 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019080 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019081 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19082 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019083 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019084 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019085 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019086 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019087 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19088 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19089 if($Vers)
19090 {
19091 if($LIB_EXT eq "so")
19092 { # value
19093 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19094 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19095 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019096 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019097 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19098 {
19099 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19100 setLanguage($LibVersion, "C++");
19101 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019102 }
19103 if($CheckObjectsOnly
19104 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019105 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019106 }
19107 }
19108 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019109 elsif($LIB_TYPE eq "dynamic")
19110 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019111 if($Deps)
19112 {
19113 if(/NEEDED.+\[([^\[\]]+)\]/)
19114 { # dependencies:
19115 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19116 $NeededLib{$1} = 1;
19117 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019118 }
19119 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019120 }
19121 close(LIB);
19122 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019123 if($Vers)
19124 {
19125 if(not $IsNeededLib and $LIB_EXT eq "so")
19126 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019127 my %Found = ();
19128
19129 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019130 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019131 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019132 next if(index($Symbol,"\@")==-1);
19133 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019134 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019135 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019136 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019137 if($Symbol_SameValue ne $Symbol
19138 and index($Symbol_SameValue,"\@")==-1)
19139 {
19140 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019141 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019142 last;
19143 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019144 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019145 }
19146 }
19147
19148 # default
19149 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19150 {
19151 next if(defined $Found{$Symbol});
19152 next if(index($Symbol,"\@\@")==-1);
19153
19154 if($Symbol=~/\A([^\@]*)\@\@/
19155 and not $SymVer{$LibVersion}{$1})
19156 {
19157 $SymVer{$LibVersion}{$1} = $Symbol;
19158 $Found{$Symbol} = 1;
19159 }
19160 }
19161
19162 # non-default
19163 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19164 {
19165 next if(defined $Found{$Symbol});
19166 next if(index($Symbol,"\@")==-1);
19167
19168 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19169 and not $SymVer{$LibVersion}{$1})
19170 {
19171 $SymVer{$LibVersion}{$1} = $Symbol;
19172 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019173 }
19174 }
19175 }
19176 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019177 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019178 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019179 foreach my $DyLib (sort keys(%NeededLib))
19180 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019181 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19182
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019183 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19184 {
19185 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19186 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19187 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019188 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019189 }
19190 }
19191 pop(@RecurLib);
19192 return $Library_Symbol{$LibVersion};
19193}
19194
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019195sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019196{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019197 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019198 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019199 return keys(%Prefixes);
19200}
19201
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019202sub get_prefixes_I($$)
19203{
19204 foreach my $P (@{$_[0]})
19205 {
19206 my @Parts = reverse(split(/[\/\\]+/, $P));
19207 my $Name = $Parts[0];
19208 foreach (1 .. $#Parts)
19209 {
19210 $_[1]->{$Name}{$P} = 1;
19211 last if($_>4 or $Parts[$_] eq "include");
19212 $Name = $Parts[$_].$SLASH.$Name;
19213 }
19214 }
19215}
19216
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019217sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019218{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019219 $Cache{"checkSystemFiles"} = 1;
19220
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019221 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019222
19223 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019224 {
19225 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019226
19227 my @Files = cmd_find($DevelPath);
19228
19229 if(not $CheckObjectsOnly)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019230 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019231 # search for headers in /usr/lib
19232 @SysHeaders = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19233 @SysHeaders = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @SysHeaders;
19234 }
19235
19236 # search for libraries in /usr/lib (including symbolic links)
19237 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19238 foreach my $Path (@Libs)
19239 {
19240 my $N = get_filename($Path);
19241 $SystemObjects{$N}{$Path} = 1;
19242 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019243 }
19244 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019245
19246 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019247 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019248 foreach my $DevelPath (@{$SystemPaths{"include"}})
19249 {
19250 next if(not -d $DevelPath);
19251 # search for all header files in the /usr/include
19252 # with or without extension (ncurses.h, QtCore, ...)
19253 push(@SysHeaders, cmd_find($DevelPath,"f"));
19254 foreach my $Link (cmd_find($DevelPath,"l"))
19255 { # add symbolic links
19256 if(-f $Link) {
19257 push(@SysHeaders, $Link);
19258 }
19259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019260 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019261 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019262 }
19263}
19264
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019265sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019266{
19267 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019268 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019269 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19270 {
19271 if(not -e $Dest) {
19272 exitStatus("Access_Error", "can't access \'$Dest\'");
19273 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019274 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019275 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19276 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019277 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019278 }
19279 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019280 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019281}
19282
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019283sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019284{
19285 my ($Path, $LibVersion) = @_;
19286 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019287 my $Name = get_filename($Path);
19288 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019289 return 1;
19290 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019291 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019292 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19293 return 1;
19294 }
19295 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19296 {
19297 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19298 return 1;
19299 }
19300 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019301 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019302 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019303 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019304 return 1;
19305 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019306 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019307 return 1;
19308 }
19309 }
19310 return 0;
19311}
19312
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019313sub specificHeader($$)
19314{
19315 my ($Header, $Spec) = @_;
19316 my $Name = get_filename($Header);
19317
19318 if($Spec eq "windows")
19319 {# MS Windows
19320 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19321 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19322 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19323 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19324 my @Dirs = (
19325 "win32",
19326 "win64",
19327 "win",
19328 "windows",
19329 "msvcrt"
19330 ); # /gsf-win32/
19331 if(my $DIRs = join("|", @Dirs)) {
19332 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19333 }
19334 }
19335 elsif($Spec eq "macos")
19336 { # Mac OS
19337 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19338 }
19339
19340 return 0;
19341}
19342
19343sub skipAlienHeader($)
19344{
19345 my $Path = $_[0];
19346 my $Name = get_filename($Path);
19347 my $Dir = get_dirname($Path);
19348
19349 if($Tolerance=~/2/)
19350 { # 2 - skip internal headers
19351 my @Terms = (
19352 "p",
19353 "priv",
19354 "int",
19355 "impl",
19356 "implementation",
19357 "internal",
19358 "private",
19359 "old",
19360 "compat",
19361 "debug",
19362 "test",
19363 "gen"
19364 );
19365
19366 my @Dirs = (
19367 "private",
19368 "priv",
19369 "port",
19370 "impl",
19371 "internal",
19372 "detail",
19373 "details",
19374 "old",
19375 "compat",
19376 "debug",
19377 "config",
19378 "compiler",
19379 "platform",
19380 "test"
19381 );
19382
19383 if(my $TERMs = join("|", @Terms)) {
19384 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19385 }
19386 if(my $DIRs = join("|", @Dirs)) {
19387 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19388 }
19389
19390 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19391 }
19392
19393 if($Tolerance=~/1/)
19394 { # 1 - skip non-Linux headers
19395 if($OSgroup ne "windows")
19396 {
19397 if(specificHeader($Path, "windows")) {
19398 return 1;
19399 }
19400 }
19401 if($OSgroup ne "macos")
19402 {
19403 if(specificHeader($Path, "macos")) {
19404 return 1;
19405 }
19406 }
19407 }
19408
19409 # valid
19410 return 0;
19411}
19412
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019413sub skipHeader($$)
19414{
19415 my ($Path, $LibVersion) = @_;
19416 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019417 if(defined $Cache{"skipHeader"}{$Path}) {
19418 return $Cache{"skipHeader"}{$Path};
19419 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019420 if(defined $Tolerance and $Tolerance=~/1|2/)
19421 { # --tolerant
19422 if(skipAlienHeader($Path)) {
19423 return ($Cache{"skipHeader"}{$Path} = 1);
19424 }
19425 }
19426 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19427 return 0;
19428 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019429 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19430}
19431
19432sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019433{ # returns:
19434 # 1 - if header should NOT be included and checked
19435 # 2 - if header should NOT be included, but should be checked
19436 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019437 my $Name = get_filename($Path);
19438 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019439 return $Kind;
19440 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019441 foreach my $D (keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019442 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019443 if(index($Path, $D)!=-1)
19444 {
19445 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19446 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19447 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019448 }
19449 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019450 foreach my $P (keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019451 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019452 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19453 {
19454 if($Name=~/$P/) {
19455 return $Kind;
19456 }
19457 if($P=~/[\/\\]/ and $Path=~/$P/) {
19458 return $Kind;
19459 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019460 }
19461 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019462
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019463 return 0;
19464}
19465
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019466sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019467{
19468 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019469 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019470 { # system directory
19471 return;
19472 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019473 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019474 { # already registered
19475 return;
19476 }
19477 foreach my $Path (find_libs($Dir,"",1))
19478 {
19479 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019480 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019481 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019482 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019483 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19484}
19485
19486sub registerObject($$)
19487{
19488 my ($Path, $LibVersion) = @_;
19489 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019490 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019491 if($OSgroup=~/linux|bsd/i)
19492 {
19493 if(my $SONAME = getSONAME($Path)) {
19494 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19495 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019496 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019497 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19498 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019499 }
19500}
19501
19502sub getSONAME($)
19503{
19504 my $Path = $_[0];
19505 return if(not $Path);
19506 if(defined $Cache{"getSONAME"}{$Path}) {
19507 return $Cache{"getSONAME"}{$Path};
19508 }
19509 my $ObjdumpCmd = get_CmdPath("objdump");
19510 if(not $ObjdumpCmd) {
19511 exitStatus("Not_Found", "can't find \"objdump\"");
19512 }
19513 my $SonameCmd = "$ObjdumpCmd -x $Path 2>$TMP_DIR/null";
19514 if($OSgroup eq "windows") {
19515 $SonameCmd .= " | find \"SONAME\"";
19516 }
19517 else {
19518 $SonameCmd .= " | grep SONAME";
19519 }
19520 if(my $SonameInfo = `$SonameCmd`) {
19521 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19522 return ($Cache{"getSONAME"}{$Path} = $1);
19523 }
19524 }
19525 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019526}
19527
19528sub getSOPaths_Dest($$)
19529{
19530 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019531 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019532 return ();
19533 }
19534 if(-f $Dest)
19535 {
19536 if(not parse_libname($Dest, "name", $OStarget)) {
19537 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19538 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019539 registerObject($Dest, $LibVersion);
19540 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019541 return ($Dest);
19542 }
19543 elsif(-d $Dest)
19544 {
19545 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019546 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019547 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019548 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19549 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019550 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019551 { # all files and symlinks that match the name of a library
19552 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19553 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019554 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019555 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019556 }
19557 }
19558 }
19559 else
19560 { # search for all files and symlinks
19561 foreach my $Path (find_libs($Dest,"",""))
19562 {
19563 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019564 next if(skipLib($Path, $LibVersion));
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 if($OSgroup eq "macos")
19569 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019570 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019571 {
19572 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019573 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019574 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019575 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19576 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019577 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019578 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019579 }
19580 }
19581 }
19582 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019583 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019584 }
19585 else {
19586 return ();
19587 }
19588}
19589
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019590sub isCyclical($$)
19591{
19592 my ($Stack, $Value) = @_;
19593 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019594}
19595
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019596sub detectWordSize()
19597{
19598 return "" if(not $GCC_PATH);
19599 if($Cache{"detectWordSize"}) {
19600 return $Cache{"detectWordSize"};
19601 }
19602 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019603 my $Defines = `$GCC_PATH -E -dD \"$TMP_DIR/empty.h\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019604 unlink("$TMP_DIR/empty.h");
19605 my $WSize = 0;
19606 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019607 { # GCC 4
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019608 $WSize = $1;
19609 }
19610 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019611 { # GCC 3
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019612 my $PTRDIFF = $1;
19613 if($PTRDIFF=~/long/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019614 $WSize = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019615 }
19616 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019617 $WSize = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019618 }
19619 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019620 if(not $WSize) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019621 exitStatus("Error", "can't check WORD size");
19622 }
19623 return ($Cache{"detectWordSize"} = $WSize);
19624}
19625
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019626sub getWordSize($) {
19627 return $WORD_SIZE{$_[0]};
19628}
19629
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019630sub majorVersion($)
19631{
19632 my $V = $_[0];
19633 return 0 if(not $V);
19634 my @VParts = split(/\./, $V);
19635 return $VParts[0];
19636}
19637
19638sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019639{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019640 my ($V1, $V2) = @_;
19641 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019642 my @V1Parts = split(/\./, $V1);
19643 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019644 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19645 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019646 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19647 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19648 }
19649 return -1 if($#V1Parts < $#V2Parts);
19650 return 1 if($#V1Parts > $#V2Parts);
19651 return 0;
19652}
19653
19654sub read_ABI_Dump($$)
19655{
19656 my ($LibVersion, $Path) = @_;
19657 return if(not $LibVersion or not -e $Path);
19658 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019659 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019660 { # input *.abi
19661 $FilePath = $Path;
19662 }
19663 else
19664 { # input *.abi.tar.gz
19665 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019666 if(not isDump_U($FilePath)) {
19667 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019669 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019670
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019671 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019672
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019673 my $Line = readLineNum($FilePath, 0);
19674 if($Line=~/xml/)
19675 { # XML format
19676 loadModule("XmlDump");
19677 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019678 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019679 else
19680 { # Perl Data::Dumper format (default)
19681 open(DUMP, $FilePath);
19682 local $/ = undef;
19683 my $Content = <DUMP>;
19684 close(DUMP);
19685
19686 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19687 { # remove temp file
19688 unlink($FilePath);
19689 }
19690 if($Content!~/};\s*\Z/) {
19691 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19692 }
19693 $ABI = eval($Content);
19694 if(not $ABI) {
19695 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19696 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019697 }
19698 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019699 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019700 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019701 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019702 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019703 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019704 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019705 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019706
19707 if($ABI->{"ABI_DUMP_VERSION"})
19708 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019709 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019710 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019711 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019712 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019713 }
19714 else
19715 { # support for old ABI dumps
19716 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019717 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019718 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019719 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019720 }
19721 if(majorVersion($DVersion)<2)
19722 { # support for old ABI dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019723 if($UseOldDumps)
19724 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019725 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
19726 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019727 }
19728 }
19729 else
19730 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019731 my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019732 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019733 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019734 }
19735 exitStatus("Dump_Version", $Msg);
19736 }
19737 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019738
19739 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19740 { # DWARF ABI Dump
19741 $UseConv_Real{$LibVersion}{"P"} = 1;
19742 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19743
19744 $UsedDump{$LibVersion}{"DWARF"} = 1;
19745
19746 $TargetComponent = "module";
19747 }
19748
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019749 if(not checkDump($LibVersion, "2.11"))
19750 { # old ABI dumps
19751 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019752 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019753 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019754 { # ABI dump created with --binary option
19755 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19756 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019757 else
19758 { # default
19759 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19760 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019761
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019762 if(defined $ABI->{"Mode"}
19763 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019764 { # --ext option
19765 $ExtendedCheck = 1;
19766 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019767 if($ABI->{"Extra"}) {
19768 $ExtraDump = 1;
19769 }
19770
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019771 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019772 {
19773 $UsedDump{$LibVersion}{"L"} = $Lang;
19774 setLanguage($LibVersion, $Lang);
19775 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019776 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019777 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019778 }
19779 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019780 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019781 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019782 if(not $TInfo)
19783 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019784 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019785 }
19786 my %Tid_TDid = ();
19787 foreach my $TDid (keys(%{$TInfo}))
19788 {
19789 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19790 {
19791 $MAX_ID = $Tid if($Tid>$MAX_ID);
19792 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019793 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019794 }
19795 }
19796 my %NewID = ();
19797 foreach my $Tid (keys(%Tid_TDid))
19798 {
19799 my @TDids = keys(%{$Tid_TDid{$Tid}});
19800 if($#TDids>=1)
19801 {
19802 foreach my $TDid (@TDids)
19803 {
19804 if($TDid) {
19805 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19806 }
19807 else
19808 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019809 my $ID = ++$MAX_ID;
19810
19811 $NewID{$TDid}{$Tid} = $ID;
19812 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19813 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019814 }
19815 }
19816 }
19817 else
19818 {
19819 my $TDid = $TDids[0];
19820 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19821 }
19822 }
19823 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
19824 {
19825 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
19826 if(defined $Info{"BaseType"})
19827 {
19828 my $Bid = $Info{"BaseType"}{"Tid"};
19829 my $BDid = $Info{"BaseType"}{"TDid"};
19830 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019831 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019832 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
19833 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
19834 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019835 }
19836 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
19837 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019838 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019839 read_Machine_DumpInfo($ABI, $LibVersion);
19840 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019841 if(not $SymbolInfo{$LibVersion})
19842 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019843 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019844 }
19845 if(not keys(%{$SymbolInfo{$LibVersion}}))
19846 { # validation of old-version dumps
19847 if(not $ExtendedCheck) {
19848 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
19849 }
19850 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019851 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019852 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019853 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019854 else
19855 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019856 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019857 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019858 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019859 }
19860 if(not $DepSymbols)
19861 { # Cannot reconstruct DepSymbols. This may result in false
19862 # positives if the old dump is for library 2. Not a problem if
19863 # old dumps are only from old libraries.
19864 $DepSymbols = {};
19865 }
19866 foreach my $Symbol (keys(%{$DepSymbols})) {
19867 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
19868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019869 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019870 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
19871 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
19872 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019873 if(not $SkipTypes{$LibVersion})
19874 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019875 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019876 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019877 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019878 if(not $SkipSymbols{$LibVersion})
19879 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019880 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019881 }
19882 if(not $SkipSymbols{$LibVersion})
19883 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019884 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019885 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019886 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
19887 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
19888 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019889 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019890 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019891 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019892 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019893 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019894 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019895 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019896 if(not checkDump($LibVersion, "2.10.1")
19897 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019898 { # support for old ABI dumps: added target headers
19899 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040019900 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019901 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019902 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040019903 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019904 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019905 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019906 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019907 if(defined $ABI->{"GccConstants"})
19908 { # 3.0
19909 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
19910 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
19911 }
19912 }
19913
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019914 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019915 if(not $NestedNameSpaces{$LibVersion})
19916 { # support for old dumps
19917 # Cannot reconstruct NameSpaces. This may affect design
19918 # of the compatibility report.
19919 $NestedNameSpaces{$LibVersion} = {};
19920 }
19921 # target system type
19922 # needed to adopt HTML report
19923 if(not $DumpSystem)
19924 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019925 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019926 }
19927 # recreate environment
19928 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
19929 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019930 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019931 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019932 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19933 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019934 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019935 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019936 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019937 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19938 {
19939 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19940 setLanguage($LibVersion, "C++");
19941 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019942 }
19943 }
19944 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019945 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
19946 {
19947 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
19948 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19949 }
19950 }
19951
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019952 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019953 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019954 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019955 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019956 {
19957 if(not $Symbol_Library{$LibVersion}{$MnglName}
19958 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
19959 push(@VFunc, $MnglName);
19960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019961 }
19962 }
19963 translateSymbols(@VFunc, $LibVersion);
19964 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019965 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
19966
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019967 if(not checkDump($LibVersion, "3.0"))
19968 { # support for old ABI dumps
19969 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19970 {
19971 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
19972 {
19973 if(ref($BaseType) eq "HASH") {
19974 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
19975 }
19976 }
19977 }
19978 }
19979
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019980 if(not checkDump($LibVersion, "3.2"))
19981 { # support for old ABI dumps
19982 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19983 {
19984 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
19985 {
19986 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
19987 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
19988 }
19989 }
19990 }
19991
19992 # repair target headers list
19993 delete($TargetHeaders{$LibVersion});
19994 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040019995 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
19996 }
19997 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
19998 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019999 }
20000
20001 # non-target constants from anon enums
20002 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20003 {
20004 if(not $ExtraDump
20005 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20006 {
20007 delete($Constants{$LibVersion}{$Name});
20008 }
20009 }
20010 }
20011
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020012 if(not checkDump($LibVersion, "2.20"))
20013 { # support for old ABI dumps
20014 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20015 {
20016 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20017
20018 if($TType=~/Struct|Union|Enum|Typedef/)
20019 { # repair complex types first
20020 next;
20021 }
20022
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020023 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020024 {
20025 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20026 if($BType=~/Struct|Union|Enum/i)
20027 {
20028 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20029 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20030 }
20031 }
20032 }
20033 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20034 {
20035 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20036 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20037 if($TType=~/Struct|Union|Enum/) {
20038 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20039 }
20040 }
20041 }
20042
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020043 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020044 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020045 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20046 { # support for old ABI dumps < 2.0 (ACC 1.22)
20047 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20048 {
20049 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20050 {
20051 if($Access ne "public") {
20052 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20053 }
20054 }
20055 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20056 }
20057 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20058 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020059 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20060 { # support for old ABI dumps
20061 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20062 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020063 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20064 { # DWARF ABI Dumps
20065 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20066 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020067 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20068 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20069 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020070 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20071 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020072 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020073 foreach (keys(%{$TInfo{"Base"}})) {
20074 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020075 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020076 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020077 if($TInfo{"Type"} eq "MethodPtr")
20078 {
20079 if(defined $TInfo{"Param"})
20080 { # support for old ABI dumps <= 1.17
20081 if(not defined $TInfo{"Param"}{"0"})
20082 {
20083 my $Max = keys(%{$TInfo{"Param"}});
20084 foreach my $Pos (1 .. $Max) {
20085 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20086 }
20087 delete($TInfo{"Param"}{$Max});
20088 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20089 }
20090 }
20091 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020092 if($TInfo{"BaseType"} eq $TypeId)
20093 { # fix ABI dump
20094 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20095 }
20096 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020097 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020098 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020099 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020100 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20101 if(not $BName)
20102 { # broken type
20103 next;
20104 }
20105 if($TInfo{"Name"} eq $BName)
20106 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020107 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020108 next;
20109 }
20110 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20111 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020112 }
20113 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020114 }
20115 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20116 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020117 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020118 }
20119 }
20120
20121 if(not checkDump($LibVersion, "2.15"))
20122 { # support for old ABI dumps
20123 my %Dups = ();
20124 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20125 {
20126 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020127 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020128 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20129 { # remove template decls
20130 delete($SymbolInfo{$LibVersion}{$InfoId});
20131 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020133 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020134 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20135 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020136 { # templates
20137 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020138 }
20139 }
20140 }
20141
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020142 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20143 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020144 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20145 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20146 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20147 { # support for old ABI dumps (< 3.1)
20148 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20149 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20150 { # add "this" first parameter
20151 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20152 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20153
20154 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20155 {
20156 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20157 foreach my $Pos (reverse(0 .. $#Pos)) {
20158 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20159 }
20160 }
20161 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20162 }
20163 }
20164
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020165 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20166 { # ABI dumps have no mangled names for C-functions
20167 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20168 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020169 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20170 { # support for old ABI dumps
20171 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20172 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020173 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20174 { # DWARF ABI Dumps
20175 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20176 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020177 }
20178
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020179 $Descriptor{$LibVersion}{"Dump"} = 1;
20180}
20181
20182sub read_Machine_DumpInfo($$)
20183{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020184 my ($ABI, $LibVersion) = @_;
20185 if($ABI->{"Arch"}) {
20186 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020187 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020188 if($ABI->{"WordSize"}) {
20189 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020190 }
20191 else
20192 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020193 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020194 }
20195 if(not $WORD_SIZE{$LibVersion})
20196 { # support for old dumps (<1.23)
20197 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20198 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020199 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020200 }
20201 else
20202 {
20203 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020204 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020205 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020206 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20207 { # any "pointer"-type
20208 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020209 last;
20210 }
20211 }
20212 if($PSize)
20213 { # a pointer type size
20214 $WORD_SIZE{$LibVersion} = $PSize;
20215 }
20216 else {
20217 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20218 }
20219 }
20220 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020221 if($ABI->{"GccVersion"}) {
20222 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020223 }
20224}
20225
20226sub read_Libs_DumpInfo($$)
20227{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020228 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020229 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20230 if(not $Library_Symbol{$LibVersion})
20231 { # support for old dumps
20232 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020234 if(keys(%{$Library_Symbol{$LibVersion}})
20235 and not $DumpAPI) {
20236 $Descriptor{$LibVersion}{"Libs"} = "OK";
20237 }
20238}
20239
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020240sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020241{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020242 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020243
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020244 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020245 and not $DumpAPI) {
20246 $Descriptor{$LibVersion}{"Headers"} = "OK";
20247 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020248 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020249 { # headers info is stored in the old dumps in the different way
20250 if($UseOldDumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020251 and my $Name = $ABI->{"Headers"}{$Identity}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020252 { # support for old dumps: headers info corrected in 1.22
20253 $Identity = $Name;
20254 }
20255 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020256 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020257 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020258
20259 if(keys(%{$ABI->{"Sources"}})
20260 and not $DumpAPI) {
20261 $Descriptor{$LibVersion}{"Sources"} = "OK";
20262 }
20263 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
20264 { # headers info is stored in the old dumps in the different way
20265 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20266 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020268}
20269
20270sub find_libs($$$)
20271{
20272 my ($Path, $Type, $MaxDepth) = @_;
20273 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020274 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020275}
20276
20277sub createDescriptor($$)
20278{
20279 my ($LibVersion, $Path) = @_;
20280 if(not $LibVersion or not $Path
20281 or not -e $Path) {
20282 return "";
20283 }
20284 if(-d $Path)
20285 { # directory with headers files and shared objects
20286 return "
20287 <version>
20288 ".$TargetVersion{$LibVersion}."
20289 </version>
20290
20291 <headers>
20292 $Path
20293 </headers>
20294
20295 <libs>
20296 $Path
20297 </libs>";
20298 }
20299 else
20300 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020301 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020302 { # standard XML-descriptor
20303 return readFile($Path);
20304 }
20305 elsif(is_header($Path, 2, $LibVersion))
20306 { # header file
20307 return "
20308 <version>
20309 ".$TargetVersion{$LibVersion}."
20310 </version>
20311
20312 <headers>
20313 $Path
20314 </headers>
20315
20316 <libs>
20317 none
20318 </libs>";
20319 }
20320 elsif(parse_libname($Path, "name", $OStarget))
20321 { # shared object
20322 return "
20323 <version>
20324 ".$TargetVersion{$LibVersion}."
20325 </version>
20326
20327 <headers>
20328 none
20329 </headers>
20330
20331 <libs>
20332 $Path
20333 </libs>";
20334 }
20335 else
20336 { # standard XML-descriptor
20337 return readFile($Path);
20338 }
20339 }
20340}
20341
20342sub detect_lib_default_paths()
20343{
20344 my %LPaths = ();
20345 if($OSgroup eq "bsd")
20346 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020347 if(my $LdConfig = get_CmdPath("ldconfig"))
20348 {
20349 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20350 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020351 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20352 {
20353 my $Name = "lib".$1;
20354 if(not defined $LPaths{$Name}) {
20355 $LPaths{$Name} = $2;
20356 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020357 }
20358 }
20359 }
20360 else {
20361 printMsg("WARNING", "can't find ldconfig");
20362 }
20363 }
20364 else
20365 {
20366 if(my $LdConfig = get_CmdPath("ldconfig"))
20367 {
20368 if($SystemRoot and $OSgroup eq "linux")
20369 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20370 if(-e $SystemRoot."/etc/ld.so.conf") {
20371 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20372 }
20373 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020374 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20375 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020376 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20377 {
20378 my ($Name, $Path) = ($1, $2);
20379 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020380 if(not defined $LPaths{$Name})
20381 { # get first element from the list of available paths
20382
20383 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20384 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20385 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20386
20387 $LPaths{$Name} = $Path;
20388 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020389 }
20390 }
20391 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020392 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020393 printMsg("WARNING", "can't find ldconfig");
20394 }
20395 }
20396 return \%LPaths;
20397}
20398
20399sub detect_bin_default_paths()
20400{
20401 my $EnvPaths = $ENV{"PATH"};
20402 if($OSgroup eq "beos") {
20403 $EnvPaths.=":".$ENV{"BETOOLS"};
20404 }
20405 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020406 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020407 {
20408 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020409 next if(not $Path);
20410 if($SystemRoot
20411 and $Path=~/\A\Q$SystemRoot\E\//)
20412 { # do NOT use binaries from target system
20413 next;
20414 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020415 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020416 }
20417}
20418
20419sub detect_inc_default_paths()
20420{
20421 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020422 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020423 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020424 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020425 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020426 next if(index($Line, "/cc1plus ")!=-1);
20427
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020428 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20429 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020430 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020431 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020432 if(index($Path, "c++")!=-1
20433 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020434 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020435 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020436 if(not defined $MAIN_CPP_DIR
20437 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20438 $MAIN_CPP_DIR = $Path;
20439 }
20440 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020441 elsif(index($Path, "gcc")!=-1) {
20442 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020443 }
20444 else
20445 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020446 if($Path=~/local[\/\\]+include/)
20447 { # local paths
20448 next;
20449 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020450 if($SystemRoot
20451 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20452 { # The GCC include path for user headers is not a part of the system root
20453 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20454 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20455 next;
20456 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020457 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020458 }
20459 }
20460 }
20461 unlink("$TMP_DIR/empty.h");
20462 return %DPaths;
20463}
20464
20465sub detect_default_paths($)
20466{
20467 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20468 my $Search = $_[0];
20469 if($Search!~/inc/) {
20470 $HSearch = 0;
20471 }
20472 if($Search!~/lib/) {
20473 $LSearch = 0;
20474 }
20475 if($Search!~/bin/) {
20476 $BSearch = 0;
20477 }
20478 if($Search!~/gcc/) {
20479 $GSearch = 0;
20480 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020481 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020482 { # <search_headers> section of the XML descriptor
20483 # do NOT search for systems headers
20484 $HSearch = 0;
20485 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020486 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020487 { # <search_headers> section of the XML descriptor
20488 # do NOT search for systems headers
20489 $LSearch = 0;
20490 }
20491 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20492 { # additional search paths
20493 next if($Type eq "include" and not $HSearch);
20494 next if($Type eq "lib" and not $LSearch);
20495 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020496 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020497 }
20498 if($OSgroup ne "windows")
20499 { # unix-like
20500 foreach my $Type ("include", "lib", "bin")
20501 { # automatic detection of system "devel" directories
20502 next if($Type eq "include" and not $HSearch);
20503 next if($Type eq "lib" and not $LSearch);
20504 next if($Type eq "bin" and not $BSearch);
20505 my ($UsrDir, $RootDir) = ("/usr", "/");
20506 if($SystemRoot and $Type ne "bin")
20507 { # 1. search for target headers and libraries
20508 # 2. use host commands: ldconfig, readelf, etc.
20509 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20510 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020511 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020512 if(-d $RootDir."/".$Type)
20513 { # if "/lib" is symbolic link
20514 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020515 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020516 }
20517 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020518 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020519 }
20520 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020521 if(-d $UsrDir)
20522 {
20523 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020524 if(-d $UsrDir."/".$Type)
20525 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020526 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020527 }
20528 }
20529 }
20530 }
20531 if($BSearch)
20532 {
20533 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020534 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020535 }
20536 # check environment variables
20537 if($OSgroup eq "beos")
20538 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020539 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020540 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020541 if($_ eq ".") {
20542 next;
20543 }
20544 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20545 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20546 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020547 }
20548 }
20549 if($HSearch)
20550 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020551 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20552 split(/:|;/, $ENV{"BEINCLUDES"})
20553 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020554 }
20555 if($LSearch)
20556 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020557 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20558 split(/:|;/, $ENV{"BELIBRARIES"}),
20559 split(/:|;/, $ENV{"LIBRARY_PATH"})
20560 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020561 }
20562 }
20563 if($LSearch)
20564 { # using linker to get system paths
20565 if(my $LPaths = detect_lib_default_paths())
20566 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020567 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020568 foreach my $Name (keys(%{$LPaths}))
20569 {
20570 if($SystemRoot
20571 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20572 { # wrong ldconfig configuration
20573 # check your <sysroot>/etc/ld.so.conf
20574 next;
20575 }
20576 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020577 if(my $Dir = get_dirname($LPaths->{$Name})) {
20578 $Dirs{$Dir} = 1;
20579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020580 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020581 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020582 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020583 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020584 }
20585 if($BSearch)
20586 {
20587 if($CrossGcc)
20588 { # --cross-gcc=arm-linux-gcc
20589 if(-e $CrossGcc)
20590 { # absolute or relative path
20591 $GCC_PATH = get_abs_path($CrossGcc);
20592 }
20593 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20594 { # command name
20595 $GCC_PATH = $CrossGcc;
20596 }
20597 else {
20598 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20599 }
20600 if($GCC_PATH=~/\s/) {
20601 $GCC_PATH = "\"".$GCC_PATH."\"";
20602 }
20603 }
20604 }
20605 if($GSearch)
20606 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020607 if(not $CrossGcc)
20608 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020609 $GCC_PATH = get_CmdPath("gcc");
20610 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020611 if(not $GCC_PATH)
20612 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020613 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020614 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020615 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020616 { # select the latest version
20617 @GCCs = sort {$b cmp $a} @GCCs;
20618 if(check_gcc($GCCs[0], "3"))
20619 {
20620 $GCC_PATH = $GCCs[0];
20621 last;
20622 }
20623 }
20624 }
20625 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020626 if(not $GCC_PATH) {
20627 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20628 }
20629 if(not $CheckObjectsOnly_Opt)
20630 {
20631 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
20632 {
20633 my $GccTarget = get_dumpmachine($GCC_PATH);
20634 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget)");
20635 if($GccTarget=~/symbian/)
20636 {
20637 $OStarget = "symbian";
20638 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20639 }
20640 }
20641 else {
20642 exitStatus("Error", "something is going wrong with the GCC compiler");
20643 }
20644 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020645 if($HSearch)
20646 {
20647 if(not $NoStdInc)
20648 { # do NOT search in GCC standard paths
20649 my %DPaths = detect_inc_default_paths();
20650 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20651 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20652 @DefaultIncPaths = @{$DPaths{"Inc"}};
20653 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020654 }
20655 }
20656 }
20657 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020658 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020659 my $IncPath = "/usr/include";
20660 if($SystemRoot) {
20661 $IncPath = $SystemRoot.$IncPath;
20662 }
20663 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020664 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020665 }
20666 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020667
20668 if($ExtraInfo)
20669 {
20670 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20671 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020673}
20674
20675sub getLIB_EXT($)
20676{
20677 my $Target = $_[0];
20678 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20679 return $Ext;
20680 }
20681 return $OS_LibExt{$LIB_TYPE}{"default"};
20682}
20683
20684sub getAR_EXT($)
20685{
20686 my $Target = $_[0];
20687 if(my $Ext = $OS_Archive{$Target}) {
20688 return $Ext;
20689 }
20690 return $OS_Archive{"default"};
20691}
20692
20693sub get_dumpversion($)
20694{
20695 my $Cmd = $_[0];
20696 return "" if(not $Cmd);
20697 if($Cache{"get_dumpversion"}{$Cmd}) {
20698 return $Cache{"get_dumpversion"}{$Cmd};
20699 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020700 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020701 chomp($V);
20702 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20703}
20704
20705sub get_dumpmachine($)
20706{
20707 my $Cmd = $_[0];
20708 return "" if(not $Cmd);
20709 if($Cache{"get_dumpmachine"}{$Cmd}) {
20710 return $Cache{"get_dumpmachine"}{$Cmd};
20711 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020712 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020713 chomp($Machine);
20714 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20715}
20716
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020717sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020718{
20719 my $Cmd = $_[0];
20720 return "" if(not $Cmd);
20721 my @Options = (
20722 "--version",
20723 "-help"
20724 );
20725 foreach my $Opt (@Options)
20726 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020727 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020728 if($Info) {
20729 return 1;
20730 }
20731 }
20732 return 0;
20733}
20734
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020735sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020736{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020737 my ($Cmd, $ReqVer) = @_;
20738 return 0 if(not $Cmd or not $ReqVer);
20739 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20740 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020741 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020742 if(my $GccVer = get_dumpversion($Cmd))
20743 {
20744 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20745 if(cmpVersions($GccVer, $ReqVer)>=0) {
20746 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20747 }
20748 }
20749 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020750}
20751
20752sub get_depth($)
20753{
20754 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020755 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020756 }
20757 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20758}
20759
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020760sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020761{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020762 return if($Cache{"registerGccHeaders"}); # this function should be called once
20763
20764 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020765 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020766 my @Headers = cmd_find($Path,"f");
20767 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20768 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020769 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020770 my $FileName = get_filename($HPath);
20771 if(not defined $DefaultGccHeader{$FileName})
20772 { # skip duplicated
20773 $DefaultGccHeader{$FileName} = $HPath;
20774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020775 }
20776 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020777 $Cache{"registerGccHeaders"} = 1;
20778}
20779
20780sub registerCppHeaders()
20781{
20782 return if($Cache{"registerCppHeaders"}); # this function should be called once
20783
20784 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020785 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020786 my @Headers = cmd_find($CppDir,"f");
20787 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20788 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020789 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020790 my $FileName = get_filename($Path);
20791 if(not defined $DefaultCppHeader{$FileName})
20792 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020793 $DefaultCppHeader{$FileName} = $Path;
20794 }
20795 }
20796 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020797 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020798}
20799
20800sub parse_libname($$$)
20801{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020802 return "" if(not $_[0]);
20803 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20804 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020805 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020806 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20807}
20808
20809sub parse_libname_I($$$)
20810{
20811 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020812
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020813 if($Target eq "symbian") {
20814 return parse_libname_symbian($Name, $Type);
20815 }
20816 elsif($Target eq "windows") {
20817 return parse_libname_windows($Name, $Type);
20818 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020819
20820 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020821 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020822 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020823 { # libSDL-1.2.so.0.7.1
20824 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020825 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020826 if($Type eq "name")
20827 { # libSDL-1.2
20828 # libwbxml2
20829 return $2;
20830 }
20831 elsif($Type eq "name+ext")
20832 { # libSDL-1.2.so
20833 # libwbxml2.so
20834 return $1;
20835 }
20836 elsif($Type eq "version")
20837 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020838 if(defined $7
20839 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020840 { # 0.7.1
20841 return $7;
20842 }
20843 else
20844 { # libc-2.5.so (=>2.5 version)
20845 my $MV = $5;
20846 $MV=~s/\A[\-\_]+//g;
20847 return $MV;
20848 }
20849 }
20850 elsif($Type eq "short")
20851 { # libSDL
20852 # libwbxml2
20853 return $3;
20854 }
20855 elsif($Type eq "shortest")
20856 { # SDL
20857 # wbxml
20858 return shortest_name($3);
20859 }
20860 }
20861 return "";# error
20862}
20863
20864sub parse_libname_symbian($$)
20865{
20866 my ($Name, $Type) = @_;
20867 my $Ext = getLIB_EXT("symbian");
20868 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
20869 { # libpthread{00010001}.dso
20870 if($Type eq "name")
20871 { # libpthread{00010001}
20872 return $2;
20873 }
20874 elsif($Type eq "name+ext")
20875 { # libpthread{00010001}.dso
20876 return $1;
20877 }
20878 elsif($Type eq "version")
20879 { # 00010001
20880 my $V = $4;
20881 $V=~s/\{(.+)\}/$1/;
20882 return $V;
20883 }
20884 elsif($Type eq "short")
20885 { # libpthread
20886 return $3;
20887 }
20888 elsif($Type eq "shortest")
20889 { # pthread
20890 return shortest_name($3);
20891 }
20892 }
20893 return "";# error
20894}
20895
20896sub parse_libname_windows($$)
20897{
20898 my ($Name, $Type) = @_;
20899 my $Ext = getLIB_EXT("windows");
20900 if($Name=~/((.+?)\.$Ext)\Z/)
20901 { # netapi32.dll
20902 if($Type eq "name")
20903 { # netapi32
20904 return $2;
20905 }
20906 elsif($Type eq "name+ext")
20907 { # netapi32.dll
20908 return $1;
20909 }
20910 elsif($Type eq "version")
20911 { # DLL version embedded
20912 # at binary-level
20913 return "";
20914 }
20915 elsif($Type eq "short")
20916 { # netapi32
20917 return $2;
20918 }
20919 elsif($Type eq "shortest")
20920 { # netapi
20921 return shortest_name($2);
20922 }
20923 }
20924 return "";# error
20925}
20926
20927sub shortest_name($)
20928{
20929 my $Name = $_[0];
20930 # remove prefix
20931 $Name=~s/\A(lib|open)//;
20932 # remove suffix
20933 $Name=~s/[\W\d_]+\Z//i;
20934 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
20935 return $Name;
20936}
20937
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020938sub createSymbolsList($$$$$)
20939{
20940 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
20941 read_ABI_Dump(1, $DPath);
20942 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020943 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020944 }
20945 my %SymbolHeaderLib = ();
20946 my $Total = 0;
20947 # Get List
20948 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
20949 {
20950 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020951 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020952 next;
20953 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020954 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020955 { # skip other symbols
20956 next;
20957 }
20958 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
20959 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020960 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020961 next;
20962 }
20963 my $DyLib = $Symbol_Library{1}{$Symbol};
20964 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020965 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020966 next;
20967 }
20968 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
20969 $Total+=1;
20970 }
20971 # Draw List
20972 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
20973 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
20974 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
20975 {
20976 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
20977 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020978 my %NS_Symbol = ();
20979 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020980 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020981 }
20982 foreach my $NameSpace (sort keys(%NS_Symbol))
20983 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020984 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020985 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
20986 foreach my $Symbol (@SortedInterfaces)
20987 {
20988 my $SubReport = "";
20989 my $Signature = get_Signature($Symbol, 1);
20990 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020991 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020992 }
20993 if($Symbol=~/\A(_Z|\?)/)
20994 {
20995 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020996 $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 +040020997 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020998 else {
20999 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21000 }
21001 }
21002 else
21003 {
21004 if($Signature) {
21005 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21006 }
21007 else {
21008 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21009 }
21010 }
21011 $SYMBOLS_LIST .= $SubReport;
21012 }
21013 }
21014 $SYMBOLS_LIST .= "<br/>\n";
21015 }
21016 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021017 # clear info
21018 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21019 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21020 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21021 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021022 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021023 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021024 my $CssStyles = readModule("Styles", "SymbolsList.css");
21025 my $JScripts = readModule("Scripts", "Sections.js");
21026 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021027 my $Title = "$LName: public symbols";
21028 my $Keywords = "$LName, API, symbols";
21029 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021030 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021031 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021032 <br/><br/><hr/>\n".getReportFooter($LName, 1)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021033 <div style='height:999px;'></div></body></html>";
21034 writeFile($SaveTo, $SYMBOLS_LIST);
21035}
21036
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021037sub add_target_libs($)
21038{
21039 foreach (@{$_[0]}) {
21040 $TargetLibs{$_} = 1;
21041 }
21042}
21043
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021044sub is_target_lib($)
21045{
21046 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021047 if(not $LName) {
21048 return 0;
21049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021050 if($TargetLibraryName
21051 and $LName!~/\Q$TargetLibraryName\E/) {
21052 return 0;
21053 }
21054 if(keys(%TargetLibs)
21055 and not $TargetLibs{$LName}
21056 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21057 return 0;
21058 }
21059 return 1;
21060}
21061
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021062sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021063{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021064 my ($H, $V) = @_;
21065 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021066 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021067 if($TargetHeaders{$V}{$H}) {
21068 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021069 }
21070 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021071 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021072}
21073
21074sub checkVersionNum($$)
21075{
21076 my ($LibVersion, $Path) = @_;
21077 if(my $VerNum = $TargetVersion{$LibVersion}) {
21078 return $VerNum;
21079 }
21080 my $UsedAltDescr = 0;
21081 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021082 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021083 next if(isDump($Part)); # ABI dump
21084 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021085 my $VerNum = "";
21086 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021087 {
21088 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021089 $VerNum = parse_libname($Part, "version", $OStarget);
21090 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021091 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021092 }
21093 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021094 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
21095 {
21096 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021097 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021098 }
21099 if($VerNum ne "")
21100 {
21101 $TargetVersion{$LibVersion} = $VerNum;
21102 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021103 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021104 }
21105 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021106 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 +040021107 }
21108 return $TargetVersion{$LibVersion};
21109 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021110 }
21111 if($UsedAltDescr)
21112 {
21113 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021114 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021115 }
21116 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021117 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021118 }
21119 }
21120}
21121
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021122sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021123{
21124 my $Str = $_[0];
21125 return "" if(not $Str);
21126 $Str=~s/\Q$TargetLibraryName\E//g;
21127 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021128 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021129 return $2;
21130 }
21131 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
21132 return $V;
21133 }
21134 return "";
21135}
21136
21137sub readLibs($)
21138{
21139 my $LibVersion = $_[0];
21140 if($OStarget eq "windows")
21141 { # dumpbin.exe will crash
21142 # without VS Environment
21143 check_win32_env();
21144 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021145 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021146 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021147 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021148}
21149
21150sub dump_sorting($)
21151{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021152 my $Hash = $_[0];
21153 return [] if(not $Hash);
21154 my @Keys = keys(%{$Hash});
21155 return [] if($#Keys<0);
21156 if($Keys[0]=~/\A\d+\Z/)
21157 { # numbers
21158 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021159 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021160 else
21161 { # strings
21162 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021163 }
21164}
21165
21166sub printMsg($$)
21167{
21168 my ($Type, $Msg) = @_;
21169 if($Type!~/\AINFO/) {
21170 $Msg = $Type.": ".$Msg;
21171 }
21172 if($Type!~/_C\Z/) {
21173 $Msg .= "\n";
21174 }
21175 if($Quiet)
21176 { # --quiet option
21177 appendFile($COMMON_LOG_PATH, $Msg);
21178 }
21179 else
21180 {
21181 if($Type eq "ERROR") {
21182 print STDERR $Msg;
21183 }
21184 else {
21185 print $Msg;
21186 }
21187 }
21188}
21189
21190sub exitStatus($$)
21191{
21192 my ($Code, $Msg) = @_;
21193 printMsg("ERROR", $Msg);
21194 exit($ERROR_CODE{$Code});
21195}
21196
21197sub exitReport()
21198{ # the tool has run without any errors
21199 printReport();
21200 if($COMPILE_ERRORS)
21201 { # errors in headers may add false positives/negatives
21202 exit($ERROR_CODE{"Compile_Error"});
21203 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021204 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21205 { # --binary
21206 exit($ERROR_CODE{"Incompatible"});
21207 }
21208 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21209 { # --source
21210 exit($ERROR_CODE{"Incompatible"});
21211 }
21212 elsif($RESULT{"Source"}{"Problems"}
21213 or $RESULT{"Binary"}{"Problems"})
21214 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021215 exit($ERROR_CODE{"Incompatible"});
21216 }
21217 else {
21218 exit($ERROR_CODE{"Compatible"});
21219 }
21220}
21221
21222sub readRules($)
21223{
21224 my $Kind = $_[0];
21225 if(not -f $RULES_PATH{$Kind}) {
21226 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21227 }
21228 my $Content = readFile($RULES_PATH{$Kind});
21229 while(my $Rule = parseTag(\$Content, "rule"))
21230 {
21231 my $RId = parseTag(\$Rule, "id");
21232 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21233 foreach my $Prop (@Properties) {
21234 if(my $Value = parseTag(\$Rule, lc($Prop)))
21235 {
21236 $Value=~s/\n[ ]*//;
21237 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21238 }
21239 }
21240 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21241 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21242 }
21243 else {
21244 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21245 }
21246 }
21247}
21248
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021249sub getReportPath($)
21250{
21251 my $Level = $_[0];
21252 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21253 if($Level eq "Binary")
21254 {
21255 if($BinaryReportPath)
21256 { # --bin-report-path
21257 return $BinaryReportPath;
21258 }
21259 elsif($OutputReportPath)
21260 { # --report-path
21261 return $OutputReportPath;
21262 }
21263 else
21264 { # default
21265 return $Dir."/abi_compat_report.$ReportFormat";
21266 }
21267 }
21268 elsif($Level eq "Source")
21269 {
21270 if($SourceReportPath)
21271 { # --src-report-path
21272 return $SourceReportPath;
21273 }
21274 elsif($OutputReportPath)
21275 { # --report-path
21276 return $OutputReportPath;
21277 }
21278 else
21279 { # default
21280 return $Dir."/src_compat_report.$ReportFormat";
21281 }
21282 }
21283 else
21284 {
21285 if($OutputReportPath)
21286 { # --report-path
21287 return $OutputReportPath;
21288 }
21289 else
21290 { # default
21291 return $Dir."/compat_report.$ReportFormat";
21292 }
21293 }
21294}
21295
21296sub printStatMsg($)
21297{
21298 my $Level = $_[0];
21299 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21300}
21301
21302sub listAffected($)
21303{
21304 my $Level = $_[0];
21305 my $List = "";
21306 foreach (keys(%{$TotalAffected{$Level}}))
21307 {
21308 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21309 { # skip "Low"-severity problems
21310 next;
21311 }
21312 $List .= "$_\n";
21313 }
21314 my $Dir = get_dirname(getReportPath($Level));
21315 if($Level eq "Binary") {
21316 writeFile($Dir."/abi_affected.txt", $List);
21317 }
21318 elsif($Level eq "Source") {
21319 writeFile($Dir."/src_affected.txt", $List);
21320 }
21321}
21322
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021323sub printReport()
21324{
21325 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021326 createReport();
21327 if($JoinReport or $DoubleReport)
21328 {
21329 if($RESULT{"Binary"}{"Problems"}
21330 or $RESULT{"Source"}{"Problems"}) {
21331 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021332 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021333 else {
21334 printMsg("INFO", "result: COMPATIBLE");
21335 }
21336 printStatMsg("Binary");
21337 printStatMsg("Source");
21338 if($ListAffected)
21339 { # --list-affected
21340 listAffected("Binary");
21341 listAffected("Source");
21342 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021343 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021344 elsif($BinaryOnly)
21345 {
21346 if($RESULT{"Binary"}{"Problems"}) {
21347 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21348 }
21349 else {
21350 printMsg("INFO", "result: COMPATIBLE");
21351 }
21352 printStatMsg("Binary");
21353 if($ListAffected)
21354 { # --list-affected
21355 listAffected("Binary");
21356 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021357 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021358 elsif($SourceOnly)
21359 {
21360 if($RESULT{"Source"}{"Problems"}) {
21361 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21362 }
21363 else {
21364 printMsg("INFO", "result: COMPATIBLE");
21365 }
21366 printStatMsg("Source");
21367 if($ListAffected)
21368 { # --list-affected
21369 listAffected("Source");
21370 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021371 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021372 if($StdOut)
21373 {
21374 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021375 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021376 printMsg("INFO", "compatibility report has been generated to stdout");
21377 }
21378 else
21379 { # default
21380 printMsg("INFO", "compatibility reports have been generated to stdout");
21381 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021382 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021383 else
21384 {
21385 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021386 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021387 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21388 }
21389 elsif($DoubleReport)
21390 { # default
21391 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21392 }
21393 elsif($BinaryOnly)
21394 { # --binary
21395 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21396 }
21397 elsif($SourceOnly)
21398 { # --source
21399 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21400 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021401 }
21402}
21403
21404sub check_win32_env()
21405{
21406 if(not $ENV{"DevEnvDir"}
21407 or not $ENV{"LIB"}) {
21408 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21409 }
21410}
21411
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021412sub diffSets($$)
21413{
21414 my ($S1, $S2) = @_;
21415 my @SK1 = keys(%{$S1});
21416 my @SK2 = keys(%{$S2});
21417 if($#SK1!=$#SK2) {
21418 return 1;
21419 }
21420 foreach my $K1 (@SK1)
21421 {
21422 if(not defined $S2->{$K1}) {
21423 return 1;
21424 }
21425 }
21426 return 0;
21427}
21428
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021429sub create_ABI_Dump()
21430{
21431 if(not -e $DumpAPI) {
21432 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21433 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021434 my @DParts = split(/\s*,\s*/, $DumpAPI);
21435 foreach my $Part (@DParts)
21436 {
21437 if(not -e $Part) {
21438 exitStatus("Access_Error", "can't access \'$Part\'");
21439 }
21440 }
21441 checkVersionNum(1, $DumpAPI);
21442 foreach my $Part (@DParts)
21443 {
21444 if(isDump($Part)) {
21445 read_ABI_Dump(1, $Part);
21446 }
21447 else {
21448 readDescriptor(1, createDescriptor(1, $Part));
21449 }
21450 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021451
21452 if(not $Descriptor{1}{"Version"})
21453 { # set to default: X
21454 $Descriptor{1}{"Version"} = "X";
21455 }
21456
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021457 initLogging(1);
21458 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021459
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021460 my $DumpPath = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi";
21461 $DumpPath .= ".".$AR_EXT; # gzipped by default
21462 if($OutputDumpPath)
21463 { # user defined path
21464 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021465 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021466 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21467
21468 if(not $Archive and not $StdOut)
21469 { # check archive utilities
21470 if($OSgroup eq "windows")
21471 { # using zip
21472 my $ZipCmd = get_CmdPath("zip");
21473 if(not $ZipCmd) {
21474 exitStatus("Not_Found", "can't find \"zip\"");
21475 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021476 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021477 else
21478 { # using tar and gzip
21479 my $TarCmd = get_CmdPath("tar");
21480 if(not $TarCmd) {
21481 exitStatus("Not_Found", "can't find \"tar\"");
21482 }
21483 my $GzipCmd = get_CmdPath("gzip");
21484 if(not $GzipCmd) {
21485 exitStatus("Not_Found", "can't find \"gzip\"");
21486 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021487 }
21488 }
21489
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021490 if(not $Descriptor{1}{"Dump"})
21491 {
21492 if(not $CheckHeadersOnly) {
21493 readLibs(1);
21494 }
21495 if($CheckHeadersOnly) {
21496 setLanguage(1, "C++");
21497 }
21498 if(not $CheckObjectsOnly) {
21499 searchForHeaders(1);
21500 }
21501 $WORD_SIZE{1} = detectWordSize();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021502 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021503 if(not $Descriptor{1}{"Dump"})
21504 {
21505 if($Descriptor{1}{"Headers"}) {
21506 readHeaders(1);
21507 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021508 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021509 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021510 if(not keys(%{$SymbolInfo{1}}))
21511 { # check if created dump is valid
21512 if(not $ExtendedCheck and not $CheckObjectsOnly)
21513 {
21514 if($CheckHeadersOnly) {
21515 exitStatus("Empty_Set", "the set of public symbols is empty");
21516 }
21517 else {
21518 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21519 }
21520 }
21521 }
21522 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021523 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021524 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21525 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021526 if($ExtraDump)
21527 { # add unmangled names to the ABI dump
21528 my @Names = ();
21529 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21530 {
21531 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21532 push(@Names, $MnglName);
21533 }
21534 }
21535 translateSymbols(@Names, 1);
21536 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21537 {
21538 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21539 {
21540 if(my $Unmangled = $tr_name{$MnglName})
21541 {
21542 if($MnglName ne $Unmangled) {
21543 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21544 }
21545 }
21546 }
21547 }
21548 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021549
21550 my %GccConstants = (); # built-in GCC constants
21551 foreach my $Name (keys(%{$Constants{1}}))
21552 {
21553 if(not defined $Constants{1}{$Name}{"Header"})
21554 {
21555 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21556 delete($Constants{1}{$Name});
21557 }
21558 }
21559
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021560 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021561 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021562 "TypeInfo" => $TypeInfo{1},
21563 "SymbolInfo" => $SymbolInfo{1},
21564 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021565 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021566 "SymbolVersion" => $SymVer{1},
21567 "LibraryVersion" => $Descriptor{1}{"Version"},
21568 "LibraryName" => $TargetLibraryName,
21569 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021570 "SkipTypes" => $SkipTypes{1},
21571 "SkipSymbols" => $SkipSymbols{1},
21572 "SkipNameSpaces" => $SkipNameSpaces{1},
21573 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021574 "Headers" => \%HeadersInfo,
21575 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021576 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021577 "NameSpaces" => $NestedNameSpaces{1},
21578 "Target" => $OStarget,
21579 "Arch" => getArch(1),
21580 "WordSize" => $WORD_SIZE{1},
21581 "GccVersion" => get_dumpversion($GCC_PATH),
21582 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21583 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21584 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021585 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021586 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021587 }
21588 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021589 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021590 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021591 if($ExtendedCheck)
21592 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021593 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021594 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021595 if($BinaryOnly)
21596 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021597 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021598 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021599 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021600 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021601 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021602 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21603 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021604 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021605
21606 my $ABI_DUMP = "";
21607 if($UseXML)
21608 {
21609 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021610 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021611 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021612 else
21613 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021614 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021616 if($StdOut)
21617 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021618 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021619 printMsg("INFO", "ABI dump has been generated to stdout");
21620 return;
21621 }
21622 else
21623 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021624 my ($DDir, $DName) = separate_path($DumpPath);
21625 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021626 if(not $Archive) {
21627 $DPath = $DumpPath;
21628 }
21629
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021630 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021631
21632 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021633 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021634 close(DUMP);
21635
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021636 if(not -s $DPath) {
21637 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21638 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021639 if($Archive) {
21640 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021641 }
21642
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021643 if($OutputDumpPath) {
21644 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021645 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021646 else {
21647 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21648 }
21649 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 +040021650 }
21651}
21652
21653sub quickEmptyReports()
21654{ # Quick "empty" reports
21655 # 4 times faster than merging equal dumps
21656 # NOTE: the dump contains the "LibraryVersion" attribute
21657 # if you change the version, then your dump will be different
21658 # OVERCOME: use -v1 and v2 options for comparing dumps
21659 # and don't change version in the XML descriptor (and dumps)
21660 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21661 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21662 {
21663 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21664 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21665 if($FilePath1 and $FilePath2)
21666 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021667 my $Line = readLineNum($FilePath1, 0);
21668 if($Line=~/xml/)
21669 { # XML format
21670 # is not supported yet
21671 return;
21672 }
21673
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021674 local $/ = undef;
21675
21676 open(DUMP1, $FilePath1);
21677 my $Content1 = <DUMP1>;
21678 close(DUMP1);
21679
21680 open(DUMP2, $FilePath2);
21681 my $Content2 = <DUMP2>;
21682 close(DUMP2);
21683
21684 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021685 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021686 # clean memory
21687 undef $Content2;
21688
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021689 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021690 my $ABIdump = eval($Content1);
21691
21692 # clean memory
21693 undef $Content1;
21694
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021695 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021696 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 +040021697 }
21698 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021699 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021700 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21701 }
21702 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021703 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021704 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21705 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021706 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021707 read_Libs_DumpInfo($ABIdump, 1);
21708 read_Machine_DumpInfo($ABIdump, 1);
21709 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021710
21711 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21712 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21713
21714 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21715 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21716
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021717 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21718 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21719 exitReport();
21720 }
21721 }
21722 }
21723}
21724
21725sub initLogging($)
21726{
21727 my $LibVersion = $_[0];
21728 # create log directory
21729 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21730 if($OutputLogPath{$LibVersion})
21731 { # user-defined by -log-path option
21732 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21733 }
21734 if($LogMode ne "n") {
21735 mkpath($LOG_DIR);
21736 }
21737 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021738 if($Debug)
21739 { # debug directory
21740 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021741
21742 if(not $ExtraInfo)
21743 { # enable --extra-info
21744 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021746 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021747 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021748}
21749
21750sub writeLog($$)
21751{
21752 my ($LibVersion, $Msg) = @_;
21753 if($LogMode ne "n") {
21754 appendFile($LOG_PATH{$LibVersion}, $Msg);
21755 }
21756}
21757
21758sub resetLogging($)
21759{
21760 my $LibVersion = $_[0];
21761 if($LogMode!~/a|n/)
21762 { # remove old log
21763 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021764 if($Debug) {
21765 rmtree($DEBUG_PATH{$LibVersion});
21766 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021767 }
21768}
21769
21770sub printErrorLog($)
21771{
21772 my $LibVersion = $_[0];
21773 if($LogMode ne "n") {
21774 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21775 }
21776}
21777
21778sub isDump($)
21779{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021780 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz|\.zip|\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021781 return $1;
21782 }
21783 return 0;
21784}
21785
21786sub isDump_U($)
21787{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021788 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021789 return $1;
21790 }
21791 return 0;
21792}
21793
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021794sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021795{
21796 # read input XML descriptors or ABI dumps
21797 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021798 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021799 }
21800 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
21801 foreach my $Part (@DParts1)
21802 {
21803 if(not -e $Part) {
21804 exitStatus("Access_Error", "can't access \'$Part\'");
21805 }
21806 }
21807 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021808 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021809 }
21810 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
21811 foreach my $Part (@DParts2)
21812 {
21813 if(not -e $Part) {
21814 exitStatus("Access_Error", "can't access \'$Part\'");
21815 }
21816 }
21817 detect_default_paths("bin"); # to extract dumps
21818 if($#DParts1==0 and $#DParts2==0
21819 and isDump($Descriptor{1}{"Path"})
21820 and isDump($Descriptor{2}{"Path"}))
21821 { # optimization: equal ABI dumps
21822 quickEmptyReports();
21823 }
21824 checkVersionNum(1, $Descriptor{1}{"Path"});
21825 checkVersionNum(2, $Descriptor{2}{"Path"});
21826 printMsg("INFO", "preparation, please wait ...");
21827 foreach my $Part (@DParts1)
21828 {
21829 if(isDump($Part)) {
21830 read_ABI_Dump(1, $Part);
21831 }
21832 else {
21833 readDescriptor(1, createDescriptor(1, $Part));
21834 }
21835 }
21836 foreach my $Part (@DParts2)
21837 {
21838 if(isDump($Part)) {
21839 read_ABI_Dump(2, $Part);
21840 }
21841 else {
21842 readDescriptor(2, createDescriptor(2, $Part));
21843 }
21844 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021845
21846 if(not $Descriptor{1}{"Version"})
21847 { # set to default: X
21848 $Descriptor{1}{"Version"} = "X";
21849 }
21850
21851 if(not $Descriptor{2}{"Version"})
21852 { # set to default: Y
21853 $Descriptor{2}{"Version"} = "Y";
21854 }
21855
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021856 initLogging(1);
21857 initLogging(2);
21858 # check consistency
21859 if(not $Descriptor{1}{"Headers"}
21860 and not $Descriptor{1}{"Libs"}) {
21861 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
21862 }
21863 if(not $Descriptor{2}{"Headers"}
21864 and not $Descriptor{2}{"Libs"}) {
21865 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
21866 }
21867 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
21868 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
21869 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
21870 }
21871 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
21872 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
21873 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
21874 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021875 if(not $Descriptor{1}{"Headers"})
21876 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021877 if($CheckHeadersOnly_Opt) {
21878 exitStatus("Error", "can't find header files info in descriptor d1");
21879 }
21880 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021881 if(not $Descriptor{2}{"Headers"})
21882 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021883 if($CheckHeadersOnly_Opt) {
21884 exitStatus("Error", "can't find header files info in descriptor d2");
21885 }
21886 }
21887 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021888 or not $Descriptor{2}{"Headers"})
21889 {
21890 if(not $CheckObjectsOnly_Opt)
21891 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021892 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
21893 $CheckObjectsOnly = 1;
21894 }
21895 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021896 if(not $Descriptor{1}{"Libs"})
21897 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021898 if($CheckObjectsOnly_Opt) {
21899 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
21900 }
21901 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021902 if(not $Descriptor{2}{"Libs"})
21903 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021904 if($CheckObjectsOnly_Opt) {
21905 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
21906 }
21907 }
21908 if(not $Descriptor{1}{"Libs"}
21909 or not $Descriptor{2}{"Libs"})
21910 { # comparing standalone header files
21911 # comparing ABI dumps created with --headers-only
21912 if(not $CheckHeadersOnly_Opt)
21913 {
21914 printMsg("WARNING", "checking headers only");
21915 $CheckHeadersOnly = 1;
21916 }
21917 }
21918 if($UseDumps)
21919 { # --use-dumps
21920 # parallel processing
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021921 my $DumpPath1 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi.$AR_EXT";
21922 my $DumpPath2 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{2}{"Version"}.".abi.$AR_EXT";
21923
21924 unlink($DumpPath1);
21925 unlink($DumpPath2);
21926
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021927 my $pid = fork();
21928 if($pid)
21929 { # dump on two CPU cores
21930 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
21931 if($RelativeDirectory{1}) {
21932 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
21933 }
21934 if($OutputLogPath{1}) {
21935 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
21936 }
21937 if($CrossGcc) {
21938 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21939 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021940 if($Quiet)
21941 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021942 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021943 @PARAMS = (@PARAMS, "-logging-mode", "a");
21944 }
21945 elsif($LogMode and $LogMode ne "w")
21946 { # "w" is default
21947 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021948 }
21949 if($ExtendedCheck) {
21950 @PARAMS = (@PARAMS, "-extended");
21951 }
21952 if($UserLang) {
21953 @PARAMS = (@PARAMS, "-lang", $UserLang);
21954 }
21955 if($TargetVersion{1}) {
21956 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
21957 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021958 if($BinaryOnly) {
21959 @PARAMS = (@PARAMS, "-binary");
21960 }
21961 if($SourceOnly) {
21962 @PARAMS = (@PARAMS, "-source");
21963 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021964 if($SortDump) {
21965 @PARAMS = (@PARAMS, "-sort");
21966 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021967 if($DumpFormat and $DumpFormat ne "perl") {
21968 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
21969 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021970 if($CheckHeadersOnly) {
21971 @PARAMS = (@PARAMS, "-headers-only");
21972 }
21973 if($CheckObjectsOnly) {
21974 @PARAMS = (@PARAMS, "-objects-only");
21975 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021976 if($Debug)
21977 {
21978 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021979 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021980 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021981 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021982 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021983 exit(1);
21984 }
21985 }
21986 else
21987 { # child
21988 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
21989 if($RelativeDirectory{2}) {
21990 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
21991 }
21992 if($OutputLogPath{2}) {
21993 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
21994 }
21995 if($CrossGcc) {
21996 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21997 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021998 if($Quiet)
21999 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022000 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022001 @PARAMS = (@PARAMS, "-logging-mode", "a");
22002 }
22003 elsif($LogMode and $LogMode ne "w")
22004 { # "w" is default
22005 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022006 }
22007 if($ExtendedCheck) {
22008 @PARAMS = (@PARAMS, "-extended");
22009 }
22010 if($UserLang) {
22011 @PARAMS = (@PARAMS, "-lang", $UserLang);
22012 }
22013 if($TargetVersion{2}) {
22014 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22015 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022016 if($BinaryOnly) {
22017 @PARAMS = (@PARAMS, "-binary");
22018 }
22019 if($SourceOnly) {
22020 @PARAMS = (@PARAMS, "-source");
22021 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022022 if($SortDump) {
22023 @PARAMS = (@PARAMS, "-sort");
22024 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022025 if($DumpFormat and $DumpFormat ne "perl") {
22026 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22027 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022028 if($CheckHeadersOnly) {
22029 @PARAMS = (@PARAMS, "-headers-only");
22030 }
22031 if($CheckObjectsOnly) {
22032 @PARAMS = (@PARAMS, "-objects-only");
22033 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022034 if($Debug)
22035 {
22036 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022037 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022039 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022040 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022041 exit(1);
22042 }
22043 else {
22044 exit(0);
22045 }
22046 }
22047 waitpid($pid, 0);
22048 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022049 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22050 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022051 if($TargetLibraryFName ne $TargetLibraryName) {
22052 @CMP_PARAMS = (@CMP_PARAMS, "-l-full", $TargetLibraryFName);
22053 }
22054 if($ShowRetVal) {
22055 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22056 }
22057 if($CrossGcc) {
22058 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22059 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022060 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22061 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022062 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022063 }
22064 if($ReportFormat and $ReportFormat ne "html")
22065 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022066 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22067 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022068 if($OutputReportPath) {
22069 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22070 }
22071 if($BinaryReportPath) {
22072 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22073 }
22074 if($SourceReportPath) {
22075 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22076 }
22077 if($LoggingPath) {
22078 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22079 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022080 if($CheckHeadersOnly) {
22081 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22082 }
22083 if($CheckObjectsOnly) {
22084 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
22085 }
22086 if($BinaryOnly) {
22087 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22088 }
22089 if($SourceOnly) {
22090 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22091 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022092 if($Browse) {
22093 @CMP_PARAMS = (@CMP_PARAMS, "-browse", $Browse);
22094 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022095 if($OpenReport) {
22096 @CMP_PARAMS = (@CMP_PARAMS, "-open");
22097 }
22098 if($Debug)
22099 {
22100 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22101 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022103 system("perl", $0, @CMP_PARAMS);
22104 exit($?>>8);
22105 }
22106 if(not $Descriptor{1}{"Dump"}
22107 or not $Descriptor{2}{"Dump"})
22108 { # need GCC toolchain to analyze
22109 # header files and libraries
22110 detect_default_paths("inc|lib|gcc");
22111 }
22112 if(not $Descriptor{1}{"Dump"})
22113 {
22114 if(not $CheckHeadersOnly) {
22115 readLibs(1);
22116 }
22117 if($CheckHeadersOnly) {
22118 setLanguage(1, "C++");
22119 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022120 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022121 searchForHeaders(1);
22122 }
22123 $WORD_SIZE{1} = detectWordSize();
22124 }
22125 if(not $Descriptor{2}{"Dump"})
22126 {
22127 if(not $CheckHeadersOnly) {
22128 readLibs(2);
22129 }
22130 if($CheckHeadersOnly) {
22131 setLanguage(2, "C++");
22132 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022133 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022134 searchForHeaders(2);
22135 }
22136 $WORD_SIZE{2} = detectWordSize();
22137 }
22138 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22139 { # support for old ABI dumps
22140 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022141 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022142 {
22143 $WORD_SIZE{1} = $WORD_SIZE{2};
22144 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22145 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022146 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022147 {
22148 $WORD_SIZE{2} = $WORD_SIZE{1};
22149 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22150 }
22151 }
22152 elsif(not $WORD_SIZE{1}
22153 and not $WORD_SIZE{2})
22154 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022155 $WORD_SIZE{1} = "4";
22156 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022157 }
22158 if($Descriptor{1}{"Dump"})
22159 { # support for old ABI dumps
22160 prepareTypes(1);
22161 }
22162 if($Descriptor{2}{"Dump"})
22163 { # support for old ABI dumps
22164 prepareTypes(2);
22165 }
22166 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22167 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22168 }
22169 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022170 if(not $CheckObjectsOnly)
22171 {
22172 if($Descriptor{1}{"Headers"}
22173 and not $Descriptor{1}{"Dump"}) {
22174 readHeaders(1);
22175 }
22176 if($Descriptor{2}{"Headers"}
22177 and not $Descriptor{2}{"Dump"}) {
22178 readHeaders(2);
22179 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022180 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022181
22182 # clean memory
22183 %SystemHeaders = ();
22184 %mangled_name_gcc = ();
22185
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022186 prepareSymbols(1);
22187 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022188
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022189 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022190 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022191
22192 # Virtual Tables
22193 registerVTable(1);
22194 registerVTable(2);
22195
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022196 if(not checkDump(1, "1.22")
22197 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022198 { # support for old ABI dumps
22199 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22200 {
22201 if($ClassName=~/</)
22202 { # templates
22203 if(not defined $VirtualTable{1}{$ClassName})
22204 { # synchronize
22205 delete($VirtualTable{2}{$ClassName});
22206 }
22207 }
22208 }
22209 }
22210
22211 registerOverriding(1);
22212 registerOverriding(2);
22213
22214 setVirtFuncPositions(1);
22215 setVirtFuncPositions(2);
22216
22217 # Other
22218 addParamNames(1);
22219 addParamNames(2);
22220
22221 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022222}
22223
22224sub compareAPIs($)
22225{
22226 my $Level = $_[0];
22227 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022228 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022229 if($Level eq "Binary") {
22230 printMsg("INFO", "comparing ABIs ...");
22231 }
22232 else {
22233 printMsg("INFO", "comparing APIs ...");
22234 }
22235 if($CheckHeadersOnly
22236 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022237 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022238 detectAdded_H($Level);
22239 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022240 }
22241 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022242 { # added/removed in libs
22243 detectAdded($Level);
22244 detectRemoved($Level);
22245 }
22246 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022247 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022248 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022249 if(keys(%{$CheckedSymbols{$Level}})) {
22250 mergeConstants($Level);
22251 }
22252 }
22253 if($CheckHeadersOnly
22254 or $Level eq "Source")
22255 { # added/removed in headers
22256 mergeHeaders($Level);
22257 }
22258 else
22259 { # added/removed in libs
22260 mergeLibs($Level);
22261 if($CheckImpl
22262 and $Level eq "Binary") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022263 mergeImpl();
22264 }
22265 }
22266}
22267
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022268sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022269{
22270 my %Opts = (
22271 "OStarget"=>$OStarget,
22272 "Debug"=>$Debug,
22273 "Quiet"=>$Quiet,
22274 "LogMode"=>$LogMode,
22275 "CheckHeadersOnly"=>$CheckHeadersOnly,
22276
22277 "SystemRoot"=>$SystemRoot,
22278 "MODULES_DIR"=>$MODULES_DIR,
22279 "GCC_PATH"=>$GCC_PATH,
22280 "TargetSysInfo"=>$TargetSysInfo,
22281 "CrossPrefix"=>$CrossPrefix,
22282 "TargetLibraryName"=>$TargetLibraryName,
22283 "CrossGcc"=>$CrossGcc,
22284 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022285 "NoStdInc"=>$NoStdInc,
22286
22287 "BinaryOnly" => $BinaryOnly,
22288 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022289 );
22290 return \%Opts;
22291}
22292
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022293sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022294{
22295 my %CODE_ERROR = reverse(%ERROR_CODE);
22296 return $CODE_ERROR{$_[0]};
22297}
22298
22299sub scenario()
22300{
22301 if($StdOut)
22302 { # enable quiet mode
22303 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022304 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022305 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022306 if(not $LogMode)
22307 { # default
22308 $LogMode = "w";
22309 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022310 if($UserLang)
22311 { # --lang=C++
22312 $UserLang = uc($UserLang);
22313 $COMMON_LANGUAGE{1}=$UserLang;
22314 $COMMON_LANGUAGE{2}=$UserLang;
22315 }
22316 if($LoggingPath)
22317 {
22318 $OutputLogPath{1} = $LoggingPath;
22319 $OutputLogPath{2} = $LoggingPath;
22320 if($Quiet) {
22321 $COMMON_LOG_PATH = $LoggingPath;
22322 }
22323 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022324 if($Quick) {
22325 $ADD_TMPL_INSTANCES = 0;
22326 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022327 if($OutputDumpPath)
22328 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022329 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022330 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22331 }
22332 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022333 if($BinaryOnly and $SourceOnly)
22334 { # both --binary and --source
22335 # is the default mode
22336 $DoubleReport = 1;
22337 $JoinReport = 0;
22338 $BinaryOnly = 0;
22339 $SourceOnly = 0;
22340 if($OutputReportPath)
22341 { # --report-path
22342 $DoubleReport = 0;
22343 $JoinReport = 1;
22344 }
22345 }
22346 elsif($BinaryOnly or $SourceOnly)
22347 { # --binary or --source
22348 $DoubleReport = 0;
22349 $JoinReport = 0;
22350 }
22351 if($UseXML)
22352 { # --xml option
22353 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022354 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022355 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022356 if($ReportFormat)
22357 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022358 $ReportFormat = lc($ReportFormat);
22359 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022360 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022361 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022362 if($ReportFormat eq "htm")
22363 { # HTM == HTML
22364 $ReportFormat = "html";
22365 }
22366 elsif($ReportFormat eq "xml")
22367 { # --report-format=XML equal to --xml
22368 $UseXML = 1;
22369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022370 }
22371 else
22372 { # default: HTML
22373 $ReportFormat = "html";
22374 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022375 if($DumpFormat)
22376 { # validate
22377 $DumpFormat = lc($DumpFormat);
22378 if($DumpFormat!~/\A(xml|perl)\Z/) {
22379 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22380 }
22381 if($DumpFormat eq "xml")
22382 { # --dump-format=XML equal to --xml
22383 $UseXML = 1;
22384 }
22385 }
22386 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022387 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022388 $DumpFormat = "perl";
22389 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022390 if($Quiet and $LogMode!~/a|n/)
22391 { # --quiet log
22392 if(-f $COMMON_LOG_PATH) {
22393 unlink($COMMON_LOG_PATH);
22394 }
22395 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022396 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022397 $CheckUndefined = 1;
22398 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022399 if($TestTool and $UseDumps)
22400 { # --test && --use-dumps == --test-dump
22401 $TestDump = 1;
22402 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022403 if($Tolerant)
22404 { # enable all
22405 $Tolerance = 1234;
22406 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022407 if($Help)
22408 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022409 HELP_MESSAGE();
22410 exit(0);
22411 }
22412 if($InfoMsg) {
22413 INFO_MESSAGE();
22414 exit(0);
22415 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022416 if($ShowVersion)
22417 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022418 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.");
22419 exit(0);
22420 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022421 if($DumpVersion)
22422 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022423 printMsg("INFO", $TOOL_VERSION);
22424 exit(0);
22425 }
22426 if($ExtendedCheck) {
22427 $CheckHeadersOnly = 1;
22428 }
22429 if($SystemRoot_Opt)
22430 { # user defined root
22431 if(not -e $SystemRoot_Opt) {
22432 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22433 }
22434 $SystemRoot = $SystemRoot_Opt;
22435 $SystemRoot=~s/[\/]+\Z//g;
22436 if($SystemRoot) {
22437 $SystemRoot = get_abs_path($SystemRoot);
22438 }
22439 }
22440 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022441
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022442 if($SortDump)
22443 {
22444 $Data::Dumper::Useperl = 1;
22445 $Data::Dumper::Sortkeys = \&dump_sorting;
22446 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022447
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022448 if($TargetLibsPath)
22449 {
22450 if(not -f $TargetLibsPath) {
22451 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22452 }
22453 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22454 $TargetLibs{$Lib} = 1;
22455 }
22456 }
22457 if($TargetHeadersPath)
22458 { # --headers-list
22459 if(not -f $TargetHeadersPath) {
22460 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22461 }
22462 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22463 {
22464 $TargetHeaders{1}{$Header} = 1;
22465 $TargetHeaders{2}{$Header} = 1;
22466 }
22467 }
22468 if($TargetHeader)
22469 { # --header
22470 $TargetHeaders{1}{$TargetHeader} = 1;
22471 $TargetHeaders{2}{$TargetHeader} = 1;
22472 }
22473 if($TestTool
22474 or $TestDump)
22475 { # --test, --test-dump
22476 detect_default_paths("bin|gcc"); # to compile libs
22477 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022478 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
22479 $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022480 exit(0);
22481 }
22482 if($DumpSystem)
22483 { # --dump-system
22484 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022485 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022486 { # system XML descriptor
22487 if(not -f $DumpSystem) {
22488 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22489 }
22490 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022491 foreach (@{$Ret->{"Tools"}})
22492 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022493 push_U($SystemPaths{"bin"}, $_);
22494 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022495 }
22496 if($Ret->{"CrossPrefix"}) {
22497 $CrossPrefix = $Ret->{"CrossPrefix"};
22498 }
22499 }
22500 elsif($SystemRoot_Opt)
22501 { # -sysroot "/" option
22502 # default target: /usr/lib, /usr/include
22503 # search libs: /usr/lib and /lib
22504 if(not -e $SystemRoot."/usr/lib") {
22505 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22506 }
22507 if(not -e $SystemRoot."/lib") {
22508 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22509 }
22510 if(not -e $SystemRoot."/usr/include") {
22511 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22512 }
22513 readSystemDescriptor("
22514 <name>
22515 $DumpSystem
22516 </name>
22517 <headers>
22518 $SystemRoot/usr/include
22519 </headers>
22520 <libs>
22521 $SystemRoot/usr/lib
22522 </libs>
22523 <search_libs>
22524 $SystemRoot/lib
22525 </search_libs>");
22526 }
22527 else {
22528 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22529 }
22530 detect_default_paths("bin|gcc"); # to check symbols
22531 if($OStarget eq "windows")
22532 { # to run dumpbin.exe
22533 # and undname.exe
22534 check_win32_env();
22535 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022536 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022537 exit(0);
22538 }
22539 if($CmpSystems)
22540 { # --cmp-systems
22541 detect_default_paths("bin"); # to extract dumps
22542 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022543 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022544 exit(0);
22545 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022546 if($GenerateTemplate)
22547 {
22548 writeFile("VERSION.xml", $DescriptorTemplate."\n");
22549 printMsg("INFO", "XML-descriptor template ./VERSION.xml has been generated");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022550 exit(0);
22551 }
22552 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022553 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022554 }
22555 else
22556 { # validate library name
22557 if($TargetLibraryName=~/[\*\/\\]/) {
22558 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22559 }
22560 }
22561 if(not $TargetLibraryFName) {
22562 $TargetLibraryFName = $TargetLibraryName;
22563 }
22564 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
22565 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
22566 }
22567 if($SymbolsListPath)
22568 {
22569 if(not -f $SymbolsListPath) {
22570 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22571 }
22572 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22573 $SymbolsList{$Interface} = 1;
22574 }
22575 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022576 if($SkipSymbolsListPath)
22577 {
22578 if(not -f $SkipSymbolsListPath) {
22579 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22580 }
22581 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
22582 $SkipSymbolsList{$Interface} = 1;
22583 }
22584 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022585 if($SkipHeadersPath)
22586 {
22587 if(not -f $SkipHeadersPath) {
22588 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22589 }
22590 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022591 { # register for both versions
22592 $SkipHeadersList{1}{$Path} = 1;
22593 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022594 my ($CPath, $Type) = classifyPath($Path);
22595 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022596 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022597 }
22598 }
22599 if($ParamNamesPath)
22600 {
22601 if(not -f $ParamNamesPath) {
22602 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22603 }
22604 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22605 {
22606 if($Line=~s/\A(\w+)\;//)
22607 {
22608 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022609 if($Line=~/;(\d+);/)
22610 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022611 while($Line=~s/(\d+);(\w+)//) {
22612 $AddIntParams{$Interface}{$1}=$2;
22613 }
22614 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022615 else
22616 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022617 my $Num = 0;
22618 foreach my $Name (split(/;/, $Line)) {
22619 $AddIntParams{$Interface}{$Num++}=$Name;
22620 }
22621 }
22622 }
22623 }
22624 }
22625 if($AppPath)
22626 {
22627 if(not -f $AppPath) {
22628 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22629 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022630 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022631 $SymbolsList_App{$Interface} = 1;
22632 }
22633 }
22634 if($DumpAPI)
22635 { # --dump-abi
22636 # make an API dump
22637 create_ABI_Dump();
22638 exit($COMPILE_ERRORS);
22639 }
22640 # default: compare APIs
22641 # -d1 <path>
22642 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022643 compareInit();
22644 if($JoinReport or $DoubleReport)
22645 {
22646 compareAPIs("Binary");
22647 compareAPIs("Source");
22648 }
22649 elsif($BinaryOnly) {
22650 compareAPIs("Binary");
22651 }
22652 elsif($SourceOnly) {
22653 compareAPIs("Source");
22654 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022655 exitReport();
22656}
22657
22658scenario();