blob: aa71c06d30c815d919ebf187d8d47ca3d9a0f224 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04003# ABI Compliance Checker (ABICC) 1.99.9.1
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004# A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005#
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006# Copyright (C) 2009-2010 The Linux Foundation
7# Copyright (C) 2009-2011 Institute for System Programming, RAS
8# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04009# Copyright (C) 2011-2014 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 Ponomarenkob9ed4c92014-04-16 13:53:17 +040020# - G++ (3.0-4.7, 4.9 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 Ponomarenkob9ed4c92014-04-16 13:53:17 +040030# - MinGW (3.0-4.7, 4.9 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# =============
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040041# ABI Dumper >= 0.98
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040042#
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 Ponomarenkob9ed4c92014-04-16 13:53:17 +040067my $TOOL_VERSION = "1.99.9.1";
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 Ponomarenkod5958082014-01-23 13:36:03 +040070my $XML_REPORT_VERSION = "1.2";
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 Ponomarenko54040a12014-03-04 19:01:13 +040096$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CppIncompat, $SkipInternal,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040097$TargetArch, $GccOptions);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040098
99my $CmdName = get_filename($0);
100my %OS_LibExt = (
101 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400102 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400103 "macos"=>"dylib",
104 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400105 "symbian"=>"dso",
106 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400107 },
108 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400109 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400110 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400111 "symbian"=>"lib",
112 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400113 }
114);
115
116my %OS_Archive = (
117 "windows"=>"zip",
118 "default"=>"tar.gz"
119);
120
121my %ERROR_CODE = (
122 # Compatible verdict
123 "Compatible"=>0,
124 "Success"=>0,
125 # Incompatible verdict
126 "Incompatible"=>1,
127 # Undifferentiated error code
128 "Error"=>2,
129 # System command is not found
130 "Not_Found"=>3,
131 # Cannot access input files
132 "Access_Error"=>4,
133 # Cannot compile header files
134 "Cannot_Compile"=>5,
135 # Header compiled with errors
136 "Compile_Error"=>6,
137 # Invalid input ABI dump
138 "Invalid_Dump"=>7,
139 # Incompatible version of ABI dump
140 "Dump_Version"=>8,
141 # Cannot find a module
142 "Module_Error"=>9,
143 # Empty intersection between
144 # headers and shared objects
145 "Empty_Intersection"=>10,
146 # Empty set of symbols in headers
147 "Empty_Set"=>11
148);
149
150my %HomePage = (
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400151 "Wiki"=>"http://ispras.linuxbase.org/index.php/ABI_compliance_checker",
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400152 "Dev"=>"https://github.com/lvc/abi-compliance-checker"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400153);
154
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400155my $ShortUsage = "ABI Compliance Checker (ABICC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400156A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400157Copyright (C) 2014 ROSA Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400158License: 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 Ponomarenkod2ed4c62014-03-05 17:34:32 +0400219 "gcc-path|cross-gcc=s" => \$CrossGcc,
220 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
221 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400222 "sysroot=s" => \$SystemRoot_Opt,
223 "v1|version1|vnum=s" => \$TargetVersion{1},
224 "v2|version2=s" => \$TargetVersion{2},
225 "s|strict!" => \$StrictCompat,
226 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400227 "skip-symbols=s" => \$SkipSymbolsListPath,
228 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400229 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400230 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400231 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
232 "objects-only!" => \$CheckObjectsOnly_Opt,
233 "check-impl|check-implementation!" => \$CheckImpl,
234 "show-retval!" => \$ShowRetVal,
235 "use-dumps!" => \$UseDumps,
236 "nostdinc!" => \$NoStdInc,
237 "dump-system=s" => \$DumpSystem,
238 "sysinfo=s" => \$TargetSysInfo,
239 "cmp-systems!" => \$CmpSystems,
240 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400241 "ext|extended!" => \$ExtendedCheck,
242 "q|quiet!" => \$Quiet,
243 "stdout!" => \$StdOut,
244 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400245 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400246 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400247 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400248 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400249 "binary|bin|abi!" => \$BinaryOnly,
250 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400251 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400252# other options
253 "test!" => \$TestTool,
254 "test-dump!" => \$TestDump,
255 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400256 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400257 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400258 "p|params=s" => \$ParamNamesPath,
259 "relpath1|relpath=s" => \$RelativeDirectory{1},
260 "relpath2=s" => \$RelativeDirectory{2},
261 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400262 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400263 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400264 "bin-report-path=s" => \$BinaryReportPath,
265 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400266 "log-path=s" => \$LoggingPath,
267 "log1-path=s" => \$OutputLogPath{1},
268 "log2-path=s" => \$OutputLogPath{2},
269 "logging-mode=s" => \$LogMode,
270 "list-affected!" => \$ListAffected,
271 "l-full|lib-full=s" => \$TargetLibraryFName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400272 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400273 "b|browse=s" => \$Browse,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400274 "open!" => \$OpenReport,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400275 "extra-info=s" => \$ExtraInfo,
276 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400277 "force!" => \$Force,
278 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400279 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400280 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400281 "quick!" => \$Quick,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400282 "all-affected!" => \$AllAffected,
283 "skip-internal=s" => \$SkipInternal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400284) or ERR_MESSAGE();
285
286sub ERR_MESSAGE()
287{
288 printMsg("INFO", "\n".$ShortUsage);
289 exit($ERROR_CODE{"Error"});
290}
291
292my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
293my $SLIB_TYPE = $LIB_TYPE;
294if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
295{ # show as "shared" library
296 $SLIB_TYPE = "shared";
297}
298my $LIB_EXT = getLIB_EXT($OSgroup);
299my $AR_EXT = getAR_EXT($OSgroup);
300my $BYTE_SIZE = 8;
301my $COMMON_LOG_PATH = "logs/run.log";
302
303my $HelpMessage="
304NAME:
305 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400306 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400307
308DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400309 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400310 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
311 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
312 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
313 and/or source-level compatibility: changes in calling stack, v-table changes,
314 removed symbols, renamed fields, etc. Binary incompatibility may result in
315 crashing or incorrect behavior of applications built with an old version of
316 a library if they run on a new one. Source incompatibility may result in
317 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400318
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400319 The tool is intended for developers of software libraries and maintainers
320 of operating systems who are interested in ensuring backward compatibility,
321 i.e. allow old applications to run or to be recompiled with newer library
322 versions.
323
324 Also the tool can be used by ISVs for checking applications portability to
325 new library versions. Found issues can be taken into account when adapting
326 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400327
328 This tool is free software: you can redistribute it and/or modify it
329 under the terms of the GNU LGPL or GNU GPL.
330
331USAGE:
332 $CmdName [options]
333
334EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400335 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400336
337 OLD.xml and NEW.xml are XML-descriptors:
338
339 <version>
340 1.0
341 </version>
342
343 <headers>
344 /path1/to/header(s)/
345 /path2/to/header(s)/
346 ...
347 </headers>
348
349 <libs>
350 /path1/to/library(ies)/
351 /path2/to/library(ies)/
352 ...
353 </libs>
354
355INFORMATION OPTIONS:
356 -h|-help
357 Print this help.
358
359 -i|-info
360 Print complete info.
361
362 -v|-version
363 Print version information.
364
365 -dumpversion
366 Print the tool version ($TOOL_VERSION) and don't do anything else.
367
368GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400369 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400370 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400371
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400372 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400373 Descriptor of 1st (old) library version.
374 It may be one of the following:
375
376 1. XML-descriptor (VERSION.xml file):
377
378 <version>
379 1.0
380 </version>
381
382 <headers>
383 /path1/to/header(s)/
384 /path2/to/header(s)/
385 ...
386 </headers>
387
388 <libs>
389 /path1/to/library(ies)/
390 /path2/to/library(ies)/
391 ...
392 </libs>
393
394 ... (XML-descriptor template
395 can be generated by -d option)
396
397 2. ABI dump generated by -dump option
398 3. Directory with headers and/or $SLIB_TYPE libraries
399 4. Single header file
400 5. Single $SLIB_TYPE library
401 6. Comma separated list of headers and/or libraries
402
403 If you are using an 2-6 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400404 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400405
406 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400407 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400408
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400409 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400410 Descriptor of 2nd (new) library version.
411
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400412 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400413 Create library ABI dump for the input XML descriptor. You can
414 transfer it anywhere and pass instead of the descriptor. Also
415 it can be used for debugging the tool.
416
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400417 Supported ABI dump versions: 2.0<=V<=$ABI_DUMP_VERSION
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400418
419 -old-dumps
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400420 Enable support for old-version ABI dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0).\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400421
422sub HELP_MESSAGE() {
423 printMsg("INFO", $HelpMessage."
424MORE INFO:
425 $CmdName --info\n");
426}
427
428sub INFO_MESSAGE()
429{
430 printMsg("INFO", "$HelpMessage
431EXTRA OPTIONS:
432 -d|-descriptor-template
433 Create XML-descriptor template ./VERSION.xml
434
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400435 -app|-application PATH
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200436 This option allows one to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400437 for portability to the new library version.
438
439 -static-libs
440 Check static libraries instead of the shared ones. The <libs> section
441 of the XML-descriptor should point to static libraries location.
442
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400443 -cross-gcc|-gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400444 Path to the cross GCC compiler to use instead of the usual (host) GCC.
445
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400446 -cross-prefix|-gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400447 GCC toolchain prefix.
448
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400449 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400450 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400451 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400452
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400453 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400454 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200455 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400456
457 In general case you should specify it in the XML-descriptor:
458 <version>
459 VERSION
460 </version>
461
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400462 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400463 Specify 2nd library version outside the descriptor.
464
465 -s|-strict
466 Treat all compatibility warnings as problems. Add a number of \"Low\"
467 severity problems to the return value of the tool.
468
469 -headers-only
470 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
471 provide a low quality compatibility report with false positives and
472 without detecting of added/removed symbols.
473
474 Alternatively you can write \"none\" word to the <libs> section
475 in the XML-descriptor:
476 <libs>
477 none
478 </libs>
479
480 -objects-only
481 Check $SLIB_TYPE libraries without header files. It is easy to run, but may
482 provide a low quality compatibility report with false positives and
483 without analysis of changes in parameters and data types.
484
485 Alternatively you can write \"none\" word to the <headers> section
486 in the XML-descriptor:
487 <headers>
488 none
489 </headers>
490
491 -check-impl|-check-implementation
492 Compare canonified disassembled binary code of $SLIB_TYPE libraries to
493 detect changes in the implementation. Add \'Problems with Implementation\'
494 section to the report.
495
496 -show-retval
497 Show the symbol's return type in the report.
498
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400499 -symbols-list PATH
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200500 This option allows one to specify a file with a list of symbols (mangled
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400501 names in C++) that should be checked, other symbols will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400502
503 -skip-symbols PATH
504 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400505
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400506 -headers-list PATH
507 The file with a list of headers, that should be checked/dumped.
508
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400509 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400510 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400511
512 -header NAME
513 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400514
515 -use-dumps
516 Make dumps for two versions of a library and compare dumps. This should
517 increase the performance of the tool and decrease the system memory usage.
518
519 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400520 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400521
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400522 -dump-system NAME -sysroot DIR
523 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400524 create XML descriptors and make ABI dumps for each library. The result
525 set of ABI dumps can be compared (--cmp-systems) with the other one
526 created for other version of operating system in order to check them for
527 compatibility. Do not forget to specify -cross-gcc option if your target
528 system requires some specific version of GCC compiler (different from
529 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400530 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400531
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400532 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400533 The same as the previous option but takes an XML descriptor of the target
534 system as input, where you should describe it:
535
536 /* Primary sections */
537
538 <name>
539 /* Name of the system */
540 </name>
541
542 <headers>
543 /* The list of paths to header files and/or
544 directories with header files, one per line */
545 </headers>
546
547 <libs>
548 /* The list of paths to shared libraries and/or
549 directories with shared libraries, one per line */
550 </libs>
551
552 /* Optional sections */
553
554 <search_headers>
555 /* List of directories to be searched
556 for header files to automatically
557 generate include paths, one per line */
558 </search_headers>
559
560 <search_libs>
561 /* List of directories to be searched
562 for shared libraries to resolve
563 dependencies, one per line */
564 </search_libs>
565
566 <tools>
567 /* List of directories with tools used
568 for analysis (GCC toolchain), one per line */
569 </tools>
570
571 <cross_prefix>
572 /* GCC toolchain prefix.
573 Examples:
574 arm-linux-gnueabi
575 arm-none-symbianelf */
576 </cross_prefix>
577
578 <gcc_options>
579 /* Additional GCC options, one per line */
580 </gcc_options>
581
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400582 -sysinfo DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400583 This option may be used with -dump-system to dump ABI of operating
584 systems and configure the dumping process.
585 Default:
586 modules/Targets/{unix, symbian, windows}
587
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400588 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400589 Compare two system ABI dumps. Create compatibility reports for each
590 library and the common HTML report including the summary of test
591 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400592 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400593
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400594 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400595 The file with a list of libraries, that should be dumped by
596 the -dump-system option or should be checked by the -cmp-systems option.
597
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400598 -ext|-extended
599 If your library A is supposed to be used by other library B and you
600 want to control the ABI of B, then you should enable this option. The
601 tool will check for changes in all data types, even if they are not
602 used by any function in the library A. Such data types are not part
603 of the A library ABI, but may be a part of the ABI of the B library.
604
605 The short scheme is:
606 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
607
608 -q|-quiet
609 Print all messages to the file instead of stdout and stderr.
610 Default path (can be changed by -log-path option):
611 $COMMON_LOG_PATH
612
613 -stdout
614 Print analysis results (compatibility reports and ABI dumps) to stdout
615 instead of creating a file. This would allow piping data to other programs.
616
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400617 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400618 Change format of compatibility report.
619 Formats:
620 htm - HTML format (default)
621 xml - XML format
622
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400623 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400624 Change format of ABI dump.
625 Formats:
626 perl - Data::Dumper format (default)
627 xml - XML format
628
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400629 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400630 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400631
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400632 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400633 Set library language (C or C++). You can use this option if the tool
634 cannot auto-detect a language. This option may be useful for checking
635 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400636
637 -arch ARCH
638 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
639 ect.). The option is useful if the tool cannot detect correct architecture
640 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400641
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400642 -binary|-bin|-abi
643 Show \"Binary\" compatibility problems only.
644 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400645 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400646
647 -source|-src|-api
648 Show \"Source\" compatibility problems only.
649 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400650 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400651
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400652 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400653 The maximum number of affected symbols listed under the description
654 of the changed type in the report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400655
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400656OTHER OPTIONS:
657 -test
658 Run internal tests. Create two binary incompatible versions of a sample
659 library and run the tool to check them for compatibility. This option
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200660 allows one to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400661
662 -test-dump
663 Test ability to create, read and compare ABI dumps.
664
665 -debug
666 Debugging mode. Print debug info on the screen. Save intermediate
667 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400668 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400669
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400670 Also consider using --dump option for debugging the tool.
671
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400672 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400673 If your header files are written in C language and can be compiled
674 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
675 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400676
677 -cpp-incompatible
678 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400679
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400680 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400681 Path to file with the function parameter names. It can be used
682 for improving report view if the library header files have no
683 parameter names. File format:
684
685 func1;param1;param2;param3 ...
686 func2;param1;param2;param3 ...
687 ...
688
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400689 -relpath PATH
690 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400691 for dumping the library ABI (see -dump option).
692
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400693 -relpath1 PATH
694 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400695
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400696 -relpath2 PATH
697 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400698
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400699 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400700 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400701 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400702 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400703
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400704 -sort
705 Enable sorting of data in ABI dumps.
706
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400707 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400708 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400709 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400710 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400711
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400712 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400713 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400714 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400715 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400716
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400717 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400718 Path to \"Source\" compatibility report.
719 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400720 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400721
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400722 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400723 Log path for all messages.
724 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400725 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400726
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400727 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400728 Log path for 1st version of a library.
729 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400730 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400731
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400732 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400733 Log path for 2nd version of a library.
734 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400735 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400736
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400737 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400738 Change logging mode.
739 Modes:
740 w - overwrite old logs (default)
741 a - append old logs
742 n - do not write any logs
743
744 -list-affected
745 Generate file with the list of incompatible
746 symbols beside the HTML compatibility report.
747 Use 'c++filt \@file' command from GNU binutils
748 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400749 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400750 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400751 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400752
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400753 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400754 The component name in the title and summary of the HTML report.
755 Default:
756 library
757
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400758 -l-full|-lib-full NAME
759 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400760 will be displayed a name specified by -l option.
761
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400762 -b|-browse PROGRAM
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400763 Open report(s) in the browser (firefox, opera, etc.).
764
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400765 -open
766 Open report(s) in the default browser.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400767
768 -extra-info DIR
769 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400770
771 -extra-dump
772 Create extended ABI dump containing all symbols
773 from the translation unit.
774
775 -force
776 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400777
778 -tolerance LEVEL
779 Apply a set of heuristics to successfully compile input
780 header files. You can enable several tolerance levels by
781 joining them into one string (e.g. 13, 124, etc.).
782 Levels:
783 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
784 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
785 3 - skip headers that iclude non-Linux headers
786 4 - skip headers included by others
787
788 -tolerant
789 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400790
791 -check
792 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400793
794 -quick
795 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400796
797 -skip-internal PATTERN
798 Do not check internal interfaces matched by the pattern.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400799
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400800REPORT:
801 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400802 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400803
804 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400805 logs/LIB_NAME/V1/log.txt
806 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400807
808EXIT CODES:
809 0 - Compatible. The tool has run without any errors.
810 non-zero - Incompatible or the tool has run with errors.
811
812REPORT BUGS TO:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400813 Andrey Ponomarenko <aponomarenko\@rosalab.ru>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400814
815MORE INFORMATION:
816 ".$HomePage{"Wiki"}."
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400817 ".$HomePage{"Dev"}."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400818}
819
820my $DescriptorTemplate = "
821<?xml version=\"1.0\" encoding=\"utf-8\"?>
822<descriptor>
823
824/* Primary sections */
825
826<version>
827 /* Version of the library */
828</version>
829
830<headers>
831 /* The list of paths to header files and/or
832 directories with header files, one per line */
833</headers>
834
835<libs>
836 /* The list of paths to shared libraries (*.$LIB_EXT) and/or
837 directories with shared libraries, one per line */
838</libs>
839
840/* Optional sections */
841
842<include_paths>
843 /* The list of include paths that will be provided
844 to GCC to compile library headers, one per line.
845 NOTE: If you define this section then the tool
846 will not automatically generate include paths */
847</include_paths>
848
849<add_include_paths>
850 /* The list of include paths that will be added
851 to the automatically generated include paths, one per line */
852</add_include_paths>
853
854<skip_include_paths>
855 /* The list of include paths that will be removed from the
856 list of automatically generated include paths, one per line */
857</skip_include_paths>
858
859<gcc_options>
860 /* Additional GCC options, one per line */
861</gcc_options>
862
863<include_preamble>
864 /* The list of header files that will be
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +0400865 included before other headers, one per line */
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400866</include_preamble>
867
868<defines>
869 /* The list of defines that will be added at the
870 headers compiling stage, one per line:
871 #define A B
872 #define C D */
873</defines>
874
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +0400875<add_namespaces>
876 /* The list of namespaces that should be added to the alanysis
877 if the tool cannot find them automatically, one per line */
878</add_namespaces>
879
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400880<skip_types>
881 /* The list of data types, that
882 should not be checked, one per line */
883</skip_types>
884
885<skip_symbols>
886 /* The list of functions (mangled/symbol names in C++),
887 that should not be checked, one per line */
888</skip_symbols>
889
890<skip_namespaces>
891 /* The list of C++ namespaces, that
892 should not be checked, one per line */
893</skip_namespaces>
894
895<skip_constants>
896 /* The list of constants that should
897 not be checked, one name per line */
898</skip_constants>
899
900<skip_headers>
901 /* The list of header files and/or directories
902 with header files that should not be checked, one per line */
903</skip_headers>
904
905<skip_libs>
906 /* The list of shared libraries and/or directories
907 with shared libraries that should not be checked, one per line */
908</skip_libs>
909
910<skip_including>
911 /* The list of header files, that cannot be included
912 directly (or non-self compiled ones), one per line */
913</skip_including>
914
915<search_headers>
916 /* List of directories to be searched
917 for header files to automatically
918 generate include paths, one per line. */
919</search_headers>
920
921<search_libs>
922 /* List of directories to be searched
923 for shared librariess to resolve
924 dependencies, one per line */
925</search_libs>
926
927<tools>
928 /* List of directories with tools used
929 for analysis (GCC toolchain), one per line */
930</tools>
931
932<cross_prefix>
933 /* GCC toolchain prefix.
934 Examples:
935 arm-linux-gnueabi
936 arm-none-symbianelf */
937</cross_prefix>
938
939</descriptor>";
940
941my %Operator_Indication = (
942 "not" => "~",
943 "assign" => "=",
944 "andassign" => "&=",
945 "orassign" => "|=",
946 "xorassign" => "^=",
947 "or" => "|",
948 "xor" => "^",
949 "addr" => "&",
950 "and" => "&",
951 "lnot" => "!",
952 "eq" => "==",
953 "ne" => "!=",
954 "lt" => "<",
955 "lshift" => "<<",
956 "lshiftassign" => "<<=",
957 "rshiftassign" => ">>=",
958 "call" => "()",
959 "mod" => "%",
960 "modassign" => "%=",
961 "subs" => "[]",
962 "land" => "&&",
963 "lor" => "||",
964 "rshift" => ">>",
965 "ref" => "->",
966 "le" => "<=",
967 "deref" => "*",
968 "mult" => "*",
969 "preinc" => "++",
970 "delete" => " delete",
971 "vecnew" => " new[]",
972 "vecdelete" => " delete[]",
973 "predec" => "--",
974 "postinc" => "++",
975 "postdec" => "--",
976 "plusassign" => "+=",
977 "plus" => "+",
978 "minus" => "-",
979 "minusassign" => "-=",
980 "gt" => ">",
981 "ge" => ">=",
982 "new" => " new",
983 "multassign" => "*=",
984 "divassign" => "/=",
985 "div" => "/",
986 "neg" => "-",
987 "pos" => "+",
988 "memref" => "->*",
989 "compound" => "," );
990
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400991my %UnknownOperator;
992
993my %NodeType= (
994 "array_type" => "Array",
995 "binfo" => "Other",
996 "boolean_type" => "Intrinsic",
997 "complex_type" => "Intrinsic",
998 "const_decl" => "Other",
999 "enumeral_type" => "Enum",
1000 "field_decl" => "Other",
1001 "function_decl" => "Other",
1002 "function_type" => "FunctionType",
1003 "identifier_node" => "Other",
1004 "integer_cst" => "Other",
1005 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001006 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001007 "method_type" => "MethodType",
1008 "namespace_decl" => "Other",
1009 "parm_decl" => "Other",
1010 "pointer_type" => "Pointer",
1011 "real_cst" => "Other",
1012 "real_type" => "Intrinsic",
1013 "record_type" => "Struct",
1014 "reference_type" => "Ref",
1015 "string_cst" => "Other",
1016 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001017 "template_type_parm" => "TemplateParam",
1018 "typename_type" => "TypeName",
1019 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001020 "tree_list" => "Other",
1021 "tree_vec" => "Other",
1022 "type_decl" => "Other",
1023 "union_type" => "Union",
1024 "var_decl" => "Other",
1025 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001026 "nop_expr" => "Other", #
1027 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001028 "offset_type" => "Other" );
1029
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001030my %CppKeywords_C = map {$_=>1} (
1031 # C++ 2003 keywords
1032 "public",
1033 "protected",
1034 "private",
1035 "default",
1036 "template",
1037 "new",
1038 #"asm",
1039 "dynamic_cast",
1040 "auto",
1041 "try",
1042 "namespace",
1043 "typename",
1044 "using",
1045 "reinterpret_cast",
1046 "friend",
1047 "class",
1048 "virtual",
1049 "const_cast",
1050 "mutable",
1051 "static_cast",
1052 "export",
1053 # C++0x keywords
1054 "noexcept",
1055 "nullptr",
1056 "constexpr",
1057 "static_assert",
1058 "explicit",
1059 # cannot be used as a macro name
1060 # as it is an operator in C++
1061 "and",
1062 #"and_eq",
1063 "not",
1064 #"not_eq",
1065 "or"
1066 #"or_eq",
1067 #"bitand",
1068 #"bitor",
1069 #"xor",
1070 #"xor_eq",
1071 #"compl"
1072);
1073
1074my %CppKeywords_F = map {$_=>1} (
1075 "delete",
1076 "catch",
1077 "alignof",
1078 "thread_local",
1079 "decltype",
1080 "typeid"
1081);
1082
1083my %CppKeywords_O = map {$_=>1} (
1084 "bool",
1085 "register",
1086 "inline",
1087 "operator"
1088);
1089
1090my %CppKeywords_A = map {$_=>1} (
1091 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001092 "throw",
1093 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001094);
1095
1096foreach (keys(%CppKeywords_C),
1097keys(%CppKeywords_F),
1098keys(%CppKeywords_O)) {
1099 $CppKeywords_A{$_}=1;
1100}
1101
1102# Header file extensions as described by gcc
1103my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
1104
1105my %IntrinsicMangling = (
1106 "void" => "v",
1107 "bool" => "b",
1108 "wchar_t" => "w",
1109 "char" => "c",
1110 "signed char" => "a",
1111 "unsigned char" => "h",
1112 "short" => "s",
1113 "unsigned short" => "t",
1114 "int" => "i",
1115 "unsigned int" => "j",
1116 "long" => "l",
1117 "unsigned long" => "m",
1118 "long long" => "x",
1119 "__int64" => "x",
1120 "unsigned long long" => "y",
1121 "__int128" => "n",
1122 "unsigned __int128" => "o",
1123 "float" => "f",
1124 "double" => "d",
1125 "long double" => "e",
1126 "__float80" => "e",
1127 "__float128" => "g",
1128 "..." => "z"
1129);
1130
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001131my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
1132
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001133my %StdcxxMangling = (
1134 "3std"=>"St",
1135 "3std9allocator"=>"Sa",
1136 "3std12basic_string"=>"Sb",
1137 "3std12basic_stringIcE"=>"Ss",
1138 "3std13basic_istreamIcE"=>"Si",
1139 "3std13basic_ostreamIcE"=>"So",
1140 "3std14basic_iostreamIcE"=>"Sd"
1141);
1142
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001143my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001144my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1145
1146my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001147my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001148
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001149my %ConstantSuffix = (
1150 "unsigned int"=>"u",
1151 "long"=>"l",
1152 "unsigned long"=>"ul",
1153 "long long"=>"ll",
1154 "unsigned long long"=>"ull"
1155);
1156
1157my %ConstantSuffixR =
1158reverse(%ConstantSuffix);
1159
1160my %OperatorMangling = (
1161 "~" => "co",
1162 "=" => "aS",
1163 "|" => "or",
1164 "^" => "eo",
1165 "&" => "an",#ad (addr)
1166 "==" => "eq",
1167 "!" => "nt",
1168 "!=" => "ne",
1169 "<" => "lt",
1170 "<=" => "le",
1171 "<<" => "ls",
1172 "<<=" => "lS",
1173 ">" => "gt",
1174 ">=" => "ge",
1175 ">>" => "rs",
1176 ">>=" => "rS",
1177 "()" => "cl",
1178 "%" => "rm",
1179 "[]" => "ix",
1180 "&&" => "aa",
1181 "||" => "oo",
1182 "*" => "ml",#de (deref)
1183 "++" => "pp",#
1184 "--" => "mm",#
1185 "new" => "nw",
1186 "delete" => "dl",
1187 "new[]" => "na",
1188 "delete[]" => "da",
1189 "+=" => "pL",
1190 "+" => "pl",#ps (pos)
1191 "-" => "mi",#ng (neg)
1192 "-=" => "mI",
1193 "*=" => "mL",
1194 "/=" => "dV",
1195 "&=" => "aN",
1196 "|=" => "oR",
1197 "%=" => "rM",
1198 "^=" => "eO",
1199 "/" => "dv",
1200 "->*" => "pm",
1201 "->" => "pt",#rf (ref)
1202 "," => "cm",
1203 "?" => "qu",
1204 "." => "dt",
1205 "sizeof"=> "sz"#st
1206);
1207
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001208my %Intrinsic_Keywords = map {$_=>1} (
1209 "true",
1210 "false",
1211 "_Bool",
1212 "_Complex",
1213 "const",
1214 "int",
1215 "long",
1216 "void",
1217 "short",
1218 "float",
1219 "volatile",
1220 "restrict",
1221 "unsigned",
1222 "signed",
1223 "char",
1224 "double",
1225 "class",
1226 "struct",
1227 "union",
1228 "enum"
1229);
1230
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001231my %GlibcHeader = map {$_=>1} (
1232 "aliases.h",
1233 "argp.h",
1234 "argz.h",
1235 "assert.h",
1236 "cpio.h",
1237 "ctype.h",
1238 "dirent.h",
1239 "envz.h",
1240 "errno.h",
1241 "error.h",
1242 "execinfo.h",
1243 "fcntl.h",
1244 "fstab.h",
1245 "ftw.h",
1246 "glob.h",
1247 "grp.h",
1248 "iconv.h",
1249 "ifaddrs.h",
1250 "inttypes.h",
1251 "langinfo.h",
1252 "limits.h",
1253 "link.h",
1254 "locale.h",
1255 "malloc.h",
1256 "math.h",
1257 "mntent.h",
1258 "monetary.h",
1259 "nl_types.h",
1260 "obstack.h",
1261 "printf.h",
1262 "pwd.h",
1263 "regex.h",
1264 "sched.h",
1265 "search.h",
1266 "setjmp.h",
1267 "shadow.h",
1268 "signal.h",
1269 "spawn.h",
1270 "stdarg.h",
1271 "stdint.h",
1272 "stdio.h",
1273 "stdlib.h",
1274 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001275 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001276 "tar.h",
1277 "termios.h",
1278 "time.h",
1279 "ulimit.h",
1280 "unistd.h",
1281 "utime.h",
1282 "wchar.h",
1283 "wctype.h",
1284 "wordexp.h" );
1285
1286my %GlibcDir = map {$_=>1} (
1287 "arpa",
1288 "bits",
1289 "gnu",
1290 "netinet",
1291 "net",
1292 "nfs",
1293 "rpc",
1294 "sys",
1295 "linux" );
1296
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001297my %WinHeaders = map {$_=>1} (
1298 "dos.h",
1299 "process.h",
1300 "winsock.h",
1301 "config-win.h",
1302 "mem.h",
1303 "windows.h",
1304 "winsock2.h",
1305 "crtdbg.h",
1306 "ws2tcpip.h"
1307);
1308
1309my %ObsoleteHeaders = map {$_=>1} (
1310 "iostream.h",
1311 "fstream.h"
1312);
1313
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001314my %AlienHeaders = map {$_=>1} (
1315 # Solaris
1316 "thread.h",
1317 "sys/atomic.h",
1318 # HPUX
1319 "sys/stream.h",
1320 # Symbian
1321 "AknDoc.h",
1322 # Atari ST
1323 "ext.h",
1324 "tos.h",
1325 # MS-DOS
1326 "alloc.h",
1327 # Sparc
1328 "sys/atomic.h"
1329);
1330
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001331my %ConfHeaders = map {$_=>1} (
1332 "atomic",
1333 "conf.h",
1334 "config.h",
1335 "configure.h",
1336 "build.h",
1337 "setup.h"
1338);
1339
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001340my %LocalIncludes = map {$_=>1} (
1341 "/usr/local/include",
1342 "/usr/local" );
1343
1344my %OS_AddPath=(
1345# These paths are needed if the tool cannot detect them automatically
1346 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001347 "include"=>[
1348 "/Library",
1349 "/Developer/usr/include"
1350 ],
1351 "lib"=>[
1352 "/Library",
1353 "/Developer/usr/lib"
1354 ],
1355 "bin"=>[
1356 "/Developer/usr/bin"
1357 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001358 },
1359 "beos"=>{
1360 # Haiku has GCC 2.95.3 by default
1361 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001362 "include"=>[
1363 "/boot/common",
1364 "/boot/develop"
1365 ],
1366 "lib"=>[
1367 "/boot/common/lib",
1368 "/boot/system/lib",
1369 "/boot/apps"
1370 ],
1371 "bin"=>[
1372 "/boot/common/bin",
1373 "/boot/system/bin",
1374 "/boot/develop/abi"
1375 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001376 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001377);
1378
1379my %Slash_Type=(
1380 "default"=>"/",
1381 "windows"=>"\\"
1382);
1383
1384my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1385
1386# Global Variables
1387my %COMMON_LANGUAGE=(
1388 1 => "C",
1389 2 => "C" );
1390
1391my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001392my $MAX_CPPFILT_FILE_SIZE = 50000;
1393my $CPPFILT_SUPPORT_FILE;
1394
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001395my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1396
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001397my $STDCXX_TESTING = 0;
1398my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001399my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001400
1401my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
1402my $CheckObjectsOnly = $CheckObjectsOnly_Opt;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001403
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001404my $TargetComponent;
1405
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001406my $CheckUndefined = 0;
1407
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001408# Set Target Component Name
1409if($TargetComponent_Opt) {
1410 $TargetComponent = lc($TargetComponent_Opt);
1411}
1412else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001413{ # default: library
1414 # other components: header, system, ...
1415 $TargetComponent = "library";
1416}
1417
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001418my $TOP_REF = "<a style='font-size:11px;' href='#Top'>to the top</a>";
1419
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001420my $SystemRoot;
1421
1422my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001423my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001424my %LOG_PATH;
1425my %DEBUG_PATH;
1426my %Cache;
1427my %LibInfo;
1428my $COMPILE_ERRORS = 0;
1429my %CompilerOptions;
1430my %CheckedDyLib;
1431my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1432
1433# Constants (#defines)
1434my %Constants;
1435my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001436my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001437
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001438# Extra Info
1439my %SymbolHeader;
1440my %KnownLibs;
1441
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001442# Templates
1443my %TemplateInstance;
1444my %BasicTemplate;
1445my %TemplateArg;
1446my %TemplateDecl;
1447my %TemplateMap;
1448
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001449# Types
1450my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001451my %SkipTypes = (
1452 "1"=>{},
1453 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001454my %CheckedTypes;
1455my %TName_Tid;
1456my %EnumMembName_Id;
1457my %NestedNameSpaces = (
1458 "1"=>{},
1459 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001460my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001461my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001462my %ClassVTable;
1463my %ClassVTable_Content;
1464my %VTableClass;
1465my %AllocableClass;
1466my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001467my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001468my %Class_SubClasses;
1469my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001470my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001471my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001472
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001473my %CheckedTypeInfo;
1474
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001475# Typedefs
1476my %Typedef_BaseName;
1477my %Typedef_Tr;
1478my %Typedef_Eq;
1479my %StdCxxTypedef;
1480my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001481my %MissedBase;
1482my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001483my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001484
1485# Symbols
1486my %SymbolInfo;
1487my %tr_name;
1488my %mangled_name_gcc;
1489my %mangled_name;
1490my %SkipSymbols = (
1491 "1"=>{},
1492 "2"=>{} );
1493my %SkipNameSpaces = (
1494 "1"=>{},
1495 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001496my %AddNameSpaces = (
1497 "1"=>{},
1498 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001499my %SymbolsList;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001500my %SkipSymbolsList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001501my %SymbolsList_App;
1502my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001503my %Symbol_Library = (
1504 "1"=>{},
1505 "2"=>{} );
1506my %Library_Symbol = (
1507 "1"=>{},
1508 "2"=>{} );
1509my %DepSymbol_Library = (
1510 "1"=>{},
1511 "2"=>{} );
1512my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001513 "1"=>{},
1514 "2"=>{} );
1515my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001516my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001517my %AddIntParams;
1518my %Interface_Impl;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001519my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001520my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001521my %Library_Needed= (
1522 "1"=>{},
1523 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001524
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001525# Extra Info
1526my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001527my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001528
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001529# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001530my %Include_Preamble = (
1531 "1"=>[],
1532 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001533my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001534my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001535my %HeaderName_Paths;
1536my %Header_Dependency;
1537my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001538my %Include_Paths = (
1539 "1"=>[],
1540 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001541my %INC_PATH_AUTODETECT = (
1542 "1"=>1,
1543 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001544my %Add_Include_Paths = (
1545 "1"=>[],
1546 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001547my %Skip_Include_Paths;
1548my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001549my %Header_ErrorRedirect;
1550my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001551my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001552my %Header_ShouldNotBeUsed;
1553my %RecursiveIncludes;
1554my %Header_Include_Prefix;
1555my %SkipHeaders;
1556my %SkipHeadersList=(
1557 "1"=>{},
1558 "2"=>{} );
1559my %SkipLibs;
1560my %Include_Order;
1561my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001562my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001563my %TUnit_Funcs;
1564my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001565
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001566my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001567 "1"=>0,
1568 "2"=>0 );
1569my %AutoPreambleMode = (
1570 "1"=>0,
1571 "2"=>0 );
1572my %MinGWMode = (
1573 "1"=>0,
1574 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001575my %Cpp0xMode = (
1576 "1"=>0,
1577 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001578
1579# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001580my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001581my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001582my %RegisteredSONAMEs;
1583my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001584
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001585my %CheckedArch;
1586
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001587# System Objects
1588my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001589my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001590my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001591
1592# System Headers
1593my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001594my @DefaultCppPaths;
1595my @DefaultGccPaths;
1596my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001597my %DefaultCppHeader;
1598my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001599my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001600
1601# Merging
1602my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001603my $Version;
1604my %AddedInt;
1605my %RemovedInt;
1606my %AddedInt_Virt;
1607my %RemovedInt_Virt;
1608my %VirtualReplacement;
1609my %ChangedTypedef;
1610my %CompatRules;
1611my %IncompleteRules;
1612my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001613my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001614my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001615my %ReturnedClass;
1616my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001617my %SourceAlternative;
1618my %SourceAlternative_B;
1619my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001620my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001621
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001622# Calling Conventions
1623my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001624 1=>{ "R"=>0, "P"=>0 },
1625 2=>{ "R"=>0, "P"=>0 }
1626);
1627
1628# ABI Dump
1629my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001630
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001631# OS Compliance
1632my %TargetLibs;
1633my %TargetHeaders;
1634
1635# OS Specifics
1636my $OStarget = $OSgroup;
1637my %TargetTools;
1638
1639# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001640my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001641
1642# Recursion locks
1643my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001644my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001645my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001646my @RecurInclude;
1647my @RecurConstant;
1648
1649# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001650my %SystemPaths = (
1651 "include"=>[],
1652 "lib"=>[],
1653 "bin"=>[]
1654);
1655my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001656my $GCC_PATH;
1657
1658# Symbols versioning
1659my %SymVer = (
1660 "1"=>{},
1661 "2"=>{} );
1662
1663# Problem descriptions
1664my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001665my %CompatProblems_Constants;
1666my %CompatProblems_Impl;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001667my %TotalAffected;
1668
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001669# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001670my $ContentID = 1;
1671my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1672my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1673my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1674my $ContentSpanEnd = "</span>\n";
1675my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1676my $ContentDivEnd = "</div>\n";
1677my $Content_Counter = 0;
1678
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001679# Modes
1680my $JoinReport = 1;
1681my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001682
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001683my %Severity_Val=(
1684 "High"=>3,
1685 "Medium"=>2,
1686 "Low"=>1,
1687 "Safe"=>-1
1688);
1689
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001690sub get_Modules()
1691{
1692 my $TOOL_DIR = get_dirname($0);
1693 if(not $TOOL_DIR)
1694 { # patch for MS Windows
1695 $TOOL_DIR = ".";
1696 }
1697 my @SEARCH_DIRS = (
1698 # tool's directory
1699 abs_path($TOOL_DIR),
1700 # relative path to modules
1701 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001702 # install path
1703 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001704 );
1705 foreach my $DIR (@SEARCH_DIRS)
1706 {
1707 if(not is_abs($DIR))
1708 { # relative path
1709 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1710 }
1711 if(-d $DIR."/modules") {
1712 return $DIR."/modules";
1713 }
1714 }
1715 exitStatus("Module_Error", "can't find modules");
1716}
1717
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001718my %LoadedModules = ();
1719
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001720sub loadModule($)
1721{
1722 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001723 if(defined $LoadedModules{$Name}) {
1724 return;
1725 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001726 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1727 if(not -f $Path) {
1728 exitStatus("Module_Error", "can't access \'$Path\'");
1729 }
1730 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001731 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001732}
1733
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001734sub readModule($$)
1735{
1736 my ($Module, $Name) = @_;
1737 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1738 if(not -f $Path) {
1739 exitStatus("Module_Error", "can't access \'$Path\'");
1740 }
1741 return readFile($Path);
1742}
1743
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001744sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001745{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001746 my $Number = $_[0];
1747 if(not $Number) {
1748 $Number = 1;
1749 }
1750 else {
1751 $Number = int($Number)+1;
1752 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001753 if($Number>3) {
1754 return $Number."th";
1755 }
1756 elsif($Number==1) {
1757 return "1st";
1758 }
1759 elsif($Number==2) {
1760 return "2nd";
1761 }
1762 elsif($Number==3) {
1763 return "3rd";
1764 }
1765 else {
1766 return $Number;
1767 }
1768}
1769
1770sub search_Tools($)
1771{
1772 my $Name = $_[0];
1773 return "" if(not $Name);
1774 if(my @Paths = keys(%TargetTools))
1775 {
1776 foreach my $Path (@Paths)
1777 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001778 if(-f join_P($Path, $Name)) {
1779 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001780 }
1781 if($CrossPrefix)
1782 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001783 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001784 if(-f $Candidate) {
1785 return $Candidate;
1786 }
1787 }
1788 }
1789 }
1790 else {
1791 return "";
1792 }
1793}
1794
1795sub synch_Cmd($)
1796{
1797 my $Name = $_[0];
1798 if(not $GCC_PATH)
1799 { # GCC was not found yet
1800 return "";
1801 }
1802 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001803 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001804 return $Candidate;
1805 }
1806 return "";
1807}
1808
1809sub get_CmdPath($)
1810{
1811 my $Name = $_[0];
1812 return "" if(not $Name);
1813 if(defined $Cache{"get_CmdPath"}{$Name}) {
1814 return $Cache{"get_CmdPath"}{$Name};
1815 }
1816 my %BinUtils = map {$_=>1} (
1817 "c++filt",
1818 "objdump",
1819 "readelf"
1820 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001821 if($BinUtils{$Name} and $GCC_PATH)
1822 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001823 if(my $Dir = get_dirname($GCC_PATH)) {
1824 $TargetTools{$Dir}=1;
1825 }
1826 }
1827 my $Path = search_Tools($Name);
1828 if(not $Path and $OSgroup eq "windows") {
1829 $Path = search_Tools($Name.".exe");
1830 }
1831 if(not $Path and $BinUtils{$Name})
1832 {
1833 if($CrossPrefix)
1834 { # user-defined prefix
1835 $Path = search_Cmd($CrossPrefix."-".$Name);
1836 }
1837 }
1838 if(not $Path and $BinUtils{$Name})
1839 {
1840 if(my $Candidate = synch_Cmd($Name))
1841 { # synch with GCC
1842 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001843 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001844 if(-f $Candidate) {
1845 $Path = $Candidate;
1846 }
1847 }
1848 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001849 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001850 $Path = $Candidate;
1851 }
1852 }
1853 }
1854 if(not $Path) {
1855 $Path = search_Cmd($Name);
1856 }
1857 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001858 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001859 $Path=search_Cmd($Name.".exe");
1860 }
1861 if($Path=~/\s/) {
1862 $Path = "\"".$Path."\"";
1863 }
1864 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1865}
1866
1867sub search_Cmd($)
1868{
1869 my $Name = $_[0];
1870 return "" if(not $Name);
1871 if(defined $Cache{"search_Cmd"}{$Name}) {
1872 return $Cache{"search_Cmd"}{$Name};
1873 }
1874 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1875 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1876 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001877 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001878 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001879 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001880 if(-f $CmdPath)
1881 {
1882 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001883 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001884 }
1885 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1886 }
1887 }
1888 return ($Cache{"search_Cmd"}{$Name} = "");
1889}
1890
1891sub get_CmdPath_Default($)
1892{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001893 return "" if(not $_[0]);
1894 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1895 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001896 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001897 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1898}
1899
1900sub get_CmdPath_Default_I($)
1901{ # search in PATH
1902 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001903 if($Name=~/find/)
1904 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001905 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001906 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001907 }
1908 }
1909 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001910 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001911 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001912 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001913 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001914 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001915 if($OSgroup eq "windows")
1916 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001917 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001918 return $Name;
1919 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001920 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001921 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001922 {
1923 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001924 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001925 }
1926 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001927 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001928}
1929
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001930sub classifyPath($)
1931{
1932 my $Path = $_[0];
1933 if($Path=~/[\*\[]/)
1934 { # wildcard
1935 $Path=~s/\*/.*/g;
1936 $Path=~s/\\/\\\\/g;
1937 return ($Path, "Pattern");
1938 }
1939 elsif($Path=~/[\/\\]/)
1940 { # directory or relative path
1941 return (path_format($Path, $OSgroup), "Path");
1942 }
1943 else {
1944 return ($Path, "Name");
1945 }
1946}
1947
1948sub readDescriptor($$)
1949{
1950 my ($LibVersion, $Content) = @_;
1951 return if(not $LibVersion);
1952 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1953 if(not $Content) {
1954 exitStatus("Error", "$DName is empty");
1955 }
1956 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001957 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001958 }
1959 $Content=~s/\/\*(.|\n)+?\*\///g;
1960 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001961
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001962 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1963 if($TargetVersion{$LibVersion}) {
1964 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1965 }
1966 if(not $Descriptor{$LibVersion}{"Version"}) {
1967 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1968 }
1969 if($Content=~/{RELPATH}/)
1970 {
1971 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1972 $Content =~ s/{RELPATH}/$RelDir/g;
1973 }
1974 else
1975 {
1976 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1977 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1978 }
1979 }
1980
1981 if(not $CheckObjectsOnly_Opt)
1982 {
1983 my $DHeaders = parseTag(\$Content, "headers");
1984 if(not $DHeaders) {
1985 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1986 }
1987 elsif(lc($DHeaders) ne "none")
1988 { # append the descriptor headers list
1989 if($Descriptor{$LibVersion}{"Headers"})
1990 { # multiple descriptors
1991 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
1992 }
1993 else {
1994 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1995 }
1996 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1997 {
1998 if(not -e $Path) {
1999 exitStatus("Access_Error", "can't access \'$Path\'");
2000 }
2001 }
2002 }
2003 }
2004 if(not $CheckHeadersOnly_Opt)
2005 {
2006 my $DObjects = parseTag(\$Content, "libs");
2007 if(not $DObjects) {
2008 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
2009 }
2010 elsif(lc($DObjects) ne "none")
2011 { # append the descriptor libraries list
2012 if($Descriptor{$LibVersion}{"Libs"})
2013 { # multiple descriptors
2014 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
2015 }
2016 else {
2017 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
2018 }
2019 foreach my $Path (split(/\s*\n\s*/, $DObjects))
2020 {
2021 if(not -e $Path) {
2022 exitStatus("Access_Error", "can't access \'$Path\'");
2023 }
2024 }
2025 }
2026 }
2027 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
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_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002035 }
2036 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
2037 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002038 if(not -d $Path) {
2039 exitStatus("Access_Error", "can't access directory \'$Path\'");
2040 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002041 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002042 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002043 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002044 }
2045 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
2046 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002047 if(not -d $Path) {
2048 exitStatus("Access_Error", "can't access directory \'$Path\'");
2049 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002050 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002051 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002052 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002053 $TargetTools{$Path}=1;
2054 }
2055 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
2056 $CrossPrefix = $Prefix;
2057 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002058 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002059 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
2060 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002061 if(not -d $Path) {
2062 exitStatus("Access_Error", "can't access directory \'$Path\'");
2063 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002064 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002065 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002066 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002067 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002068 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002069 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
2070 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002071 if(not -d $Path) {
2072 exitStatus("Access_Error", "can't access directory \'$Path\'");
2073 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002074 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002075 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002076 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002077 }
2078 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002079 { # skip some auto-generated include paths
2080 if(not is_abs($Path))
2081 {
2082 if(my $P = abs_path($Path)) {
2083 $Path = $P;
2084 }
2085 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002086 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002087 }
2088 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002089 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002090 my ($CPath, $Type) = classifyPath($Path);
2091 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002092 }
2093 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002094 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
2095 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002096 if($Option!~/\A\-(Wl|l|L)/)
2097 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002098 $CompilerOptions{$LibVersion} .= " ".$Option;
2099 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002100 }
2101 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
2102 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
2103 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002104 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002105 my ($CPath, $Type) = classifyPath($Path);
2106 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002107 }
2108 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
2109 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
2110 {
2111 my ($CPath, $Type) = classifyPath($Path);
2112 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
2113 }
2114 if(my $DDefines = parseTag(\$Content, "defines"))
2115 {
2116 if($Descriptor{$LibVersion}{"Defines"})
2117 { # multiple descriptors
2118 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
2119 }
2120 else {
2121 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
2122 }
2123 }
2124 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2125 {
2126 if($Order=~/\A(.+):(.+)\Z/) {
2127 $Include_Order{$LibVersion}{$1} = $2;
2128 }
2129 }
2130 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2131 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002132 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002133 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2134 }
2135 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2136 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002137 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002138 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2139 }
2140 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2141 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2142 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002143 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2144 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2145 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002146 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2147 $SkipConstants{$LibVersion}{$Constant} = 1;
2148 }
2149 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2150 {
2151 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002152 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002153 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2154 }
2155 else {
2156 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2157 }
2158 }
2159}
2160
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002161sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002162{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002163 my $CodeRef = shift(@_);
2164 my $Tag = shift(@_);
2165 if(not $Tag or not $CodeRef) {
2166 return undef;
2167 }
2168 my $Sp = 0;
2169 if(@_) {
2170 $Sp = shift(@_);
2171 }
2172 my $Start = index(${$CodeRef}, "<$Tag>");
2173 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002174 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002175 my $End = index(${$CodeRef}, "</$Tag>");
2176 if($End!=-1)
2177 {
2178 my $TS = length($Tag)+3;
2179 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2180 substr($Content, 0, $TS-1, ""); # cut start tag
2181 substr($Content, -$TS, $TS, ""); # cut end tag
2182 if(not $Sp)
2183 {
2184 $Content=~s/\A\s+//g;
2185 $Content=~s/\s+\Z//g;
2186 }
2187 if(substr($Content, 0, 1) ne "<") {
2188 $Content = xmlSpecChars_R($Content);
2189 }
2190 return $Content;
2191 }
2192 }
2193 return undef;
2194}
2195
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002196sub getInfo($)
2197{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002198 my $DumpPath = $_[0];
2199 return if(not $DumpPath or not -f $DumpPath);
2200
2201 readTUDump($DumpPath);
2202
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002203 # processing info
2204 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002205
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002206 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002207 setAnonTypedef_All();
2208 }
2209
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002210 getTypeInfo_All();
2211 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002212 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002213 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002214 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002215
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002216 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002217 %LibInfo = ();
2218 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002219 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002220 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002221 %TemplateDecl = ();
2222 %StdCxxTypedef = ();
2223 %MissedTypedef = ();
2224 %Typedef_Tr = ();
2225 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002226 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002227
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002228 # clean cache
2229 delete($Cache{"getTypeAttr"});
2230 delete($Cache{"getTypeDeclId"});
2231
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002232 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002233 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002234 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002235 }
2236 else
2237 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002238 if($BinaryOnly and not $ExtendedCheck)
2239 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002240 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002241 }
2242 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002243 remove_Unused($Version, "Extended");
2244 }
2245 }
2246
2247 if($CheckInfo)
2248 {
2249 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2250 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2251 }
2252
2253 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2254 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002255 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002256 }
2257
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002258 if($Debug) {
2259 # debugMangling($Version);
2260 }
2261}
2262
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002263sub readTUDump($)
2264{
2265 my $DumpPath = $_[0];
2266
2267 open(TU_DUMP, $DumpPath);
2268 local $/ = undef;
2269 my $Content = <TU_DUMP>;
2270 close(TU_DUMP);
2271
2272 unlink($DumpPath);
2273
2274 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002275 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002276
2277 # clean memory
2278 undef $Content;
2279
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002280 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002281
2282 foreach (0 .. $#Lines)
2283 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002284 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002285 { # get a number and attributes of a node
2286 next if(not $NodeType{$2});
2287 $LibInfo{$Version}{"info_type"}{$1}=$2;
2288 $LibInfo{$Version}{"info"}{$1}=$3;
2289 }
2290
2291 # clean memory
2292 delete($Lines[$_]);
2293 }
2294
2295 # clean memory
2296 undef @Lines;
2297}
2298
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002299sub simplifyConstants()
2300{
2301 foreach my $Constant (keys(%{$Constants{$Version}}))
2302 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002303 if(defined $Constants{$Version}{$Constant}{"Header"})
2304 {
2305 my $Value = $Constants{$Version}{$Constant}{"Value"};
2306 if(defined $EnumConstants{$Version}{$Value}) {
2307 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2308 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002309 }
2310 }
2311}
2312
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002313sub simplifyNames()
2314{
2315 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2316 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002317 if($Typedef_Eq{$Version}{$Base}) {
2318 next;
2319 }
2320 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2321 if($#Translations==0)
2322 {
2323 if(length($Translations[0])<=length($Base)) {
2324 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2325 }
2326 }
2327 else
2328 { # select most appropriate
2329 foreach my $Tr (@Translations)
2330 {
2331 if($Base=~/\A\Q$Tr\E/)
2332 {
2333 $Typedef_Eq{$Version}{$Base} = $Tr;
2334 last;
2335 }
2336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002337 }
2338 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002339 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002340 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002341 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002342 if(not $TypeName) {
2343 next;
2344 }
2345 next if(index($TypeName,"<")==-1);# template instances only
2346 if($TypeName=~/>(::\w+)+\Z/)
2347 { # skip unused types
2348 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002349 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002350 foreach my $Base (sort {length($b)<=>length($a)}
2351 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002352 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002353 next if(not $Base);
2354 next if(index($TypeName,$Base)==-1);
2355 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002356 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002357 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002358 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2359 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2360 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002361 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002362 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2363 {
2364 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2365 {
2366 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2367 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002368 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002369 }
2370 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002372 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002373 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002374 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002375 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2376 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002377 }
2378}
2379
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002380sub setAnonTypedef_All()
2381{
2382 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2383 {
2384 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2385 {
2386 if(isAnon(getNameByInfo($InfoId))) {
2387 $TypedefToAnon{getTypeId($InfoId)} = 1;
2388 }
2389 }
2390 }
2391}
2392
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002393sub setTemplateParams_All()
2394{
2395 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2396 {
2397 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2398 setTemplateParams($_);
2399 }
2400 }
2401}
2402
2403sub setTemplateParams($)
2404{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002405 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002406 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002407 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002408 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002409 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002410 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002411 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002412 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002413 setTemplateInstParams($_[0], $TmplInst_Id);
2414 }
2415 }
2416
2417 $BasicTemplate{$Version}{$Tid} = $_[0];
2418
2419 if(my $Prms = getTreeAttr_Prms($_[0]))
2420 {
2421 if(my $Valu = getTreeAttr_Valu($Prms))
2422 {
2423 my $Vector = getTreeVec($Valu);
2424 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2425 {
2426 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2427 {
2428 if(my $Name = getNameByInfo($Val))
2429 {
2430 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2431 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2432 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2433 }
2434 else {
2435 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2436 }
2437 }
2438 }
2439 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002440 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002441 }
2442 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002443 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002444 {
2445 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2446 {
2447 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002448 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002449 }
2450 }
2451 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002452}
2453
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002454sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002455{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002456 my ($Tmpl, $Inst) = @_;
2457
2458 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002459 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002460 my ($Params_InfoId, $ElemId) = ();
2461 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2462 $Params_InfoId = $1;
2463 }
2464 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2465 $ElemId = $1;
2466 }
2467 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002468 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002469 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2470 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2471 {
2472 my ($PPos, $PTypeId) = ($1, $2);
2473 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2474 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002475 if($PType eq "template_type_parm") {
2476 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002477 }
2478 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002479 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2480 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002481 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002482 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002483 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002484 else
2485 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002486 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002487 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002488 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002489 }
2490 }
2491 }
2492}
2493
2494sub getTypeDeclId($)
2495{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002496 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002497 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002498 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2499 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2500 }
2501 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2502 {
2503 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2504 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2505 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002506 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002507 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002508 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002509}
2510
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002511sub getTypeInfo_All()
2512{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002513 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002514 { # support for GCC < 4.5
2515 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2516 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2517 # FIXME: check GCC versions
2518 addMissedTypes_Pre();
2519 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002520
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002521 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002522 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002523 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2524 if($IType=~/_type\Z/ and $IType ne "function_type"
2525 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002526 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002527 }
2528 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002529
2530 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002531 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002532 "Name" => "...",
2533 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002534 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002535 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002536 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002537
2538 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002539 { # support for GCC < 4.5
2540 addMissedTypes_Post();
2541 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002542
2543 if($ADD_TMPL_INSTANCES)
2544 {
2545 # templates
2546 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2547 {
2548 if(defined $TemplateMap{$Version}{$Tid}
2549 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2550 {
2551 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2552 {
2553 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2554 {
2555 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2556 {
2557 if(my %MAttr = getTypeAttr($MembTypeId))
2558 {
2559 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2560 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2561 }
2562 }
2563 }
2564 }
2565 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2566 {
2567 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2568 {
2569 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2570
2571 if($NBid ne $Bid)
2572 {
2573 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2574 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2575 }
2576 }
2577 }
2578 }
2579 }
2580 }
2581}
2582
2583sub createType($$)
2584{
2585 my ($Attr, $LibVersion) = @_;
2586 my $NewId = ++$MAX_ID;
2587
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002588 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002589 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002590 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002591
2592 return "$NewId";
2593}
2594
2595sub instType($$$)
2596{ # create template instances
2597 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002598
2599 if(not $TypeInfo{$LibVersion}{$Tid}) {
2600 return undef;
2601 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002602 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2603
2604 foreach my $Key (sort keys(%{$Map}))
2605 {
2606 if(my $Val = $Map->{$Key})
2607 {
2608 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2609
2610 if(defined $Attr->{"NameSpace"}) {
2611 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2612 }
2613 foreach (keys(%{$Attr->{"TParam"}})) {
2614 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2615 }
2616 }
2617 else
2618 { # remove absent
2619 # _Traits, etc.
2620 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002621 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002622 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2623 }
2624 foreach (keys(%{$Attr->{"TParam"}}))
2625 {
2626 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2627 delete($Attr->{"TParam"}{$_});
2628 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002629 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002630 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2631 }
2632 }
2633 }
2634 }
2635
2636 my $Tmpl = 0;
2637
2638 if(defined $Attr->{"TParam"})
2639 {
2640 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2641 {
2642 my $PName = $Attr->{"TParam"}{$_}{"name"};
2643
2644 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2645 {
2646 my %Base = get_BaseType($PTid, $LibVersion);
2647
2648 if($Base{"Type"} eq "TemplateParam"
2649 or defined $Base{"Template"})
2650 {
2651 $Tmpl = 1;
2652 last
2653 }
2654 }
2655 }
2656 }
2657
2658 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2659 return "$Id";
2660 }
2661 else
2662 {
2663 if(not $Tmpl) {
2664 delete($Attr->{"Template"});
2665 }
2666
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002667 my $New = createType($Attr, $LibVersion);
2668
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002669 my %EMap = ();
2670 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2671 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2672 }
2673 foreach (keys(%{$Map})) {
2674 $EMap{$_} = $Map->{$_};
2675 }
2676
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002677 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2678 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002679 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002680 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002681 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002682 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002683 {
2684 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2685
2686 if($NBid ne $Bid)
2687 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002688 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2689 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002690 }
2691 }
2692 }
2693
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002694 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002695 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002696 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2697 {
2698 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2699 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2700 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002701 }
2702 }
2703
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002704 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002705 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002706 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2707 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002708 }
2709 }
2710
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002711 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2712 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002713 }
2714
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002715 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002716 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002717}
2718
2719sub addMissedTypes_Pre()
2720{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002721 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002722 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2723 { # detecting missed typedefs
2724 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2725 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002726 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002727 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002728 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002729 if($TypeType eq "Unknown")
2730 { # template_type_parm
2731 next;
2732 }
2733 my $TypeDeclId = getTypeDeclId($TypeId);
2734 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2735 my $TypedefName = getNameByInfo($MissedTDid);
2736 next if(not $TypedefName);
2737 next if($TypedefName eq "__float80");
2738 next if(isAnon($TypedefName));
2739 if(not $TypeDeclId
2740 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002741 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002742 }
2743 }
2744 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002745 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002746 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002747 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002748 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002749 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002750 next;
2751 }
2752 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002753 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002754 if(not $TypedefName) {
2755 next;
2756 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002757 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002758 my %MissedInfo = ( # typedef info
2759 "Name" => $TypedefName,
2760 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002761 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002762 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002763 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002764 my ($H, $L) = getLocation($MissedTDid);
2765 $MissedInfo{"Header"} = $H;
2766 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002767 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002768 { # other types
2769 next;
2770 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002771 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002772 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002773 next;
2774 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002775 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002776 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002777 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002778 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002779 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002780 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002781 next;
2782 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002783 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002784 next;
2785 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002786 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002787 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002788 next;
2789 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002790 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002791 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002792 next;
2793 }
2794 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002795
2796 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2797
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002798 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002799 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002800 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002801 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002802 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002803
2804 # add missed & remove other
2805 $TypeInfo{$Version} = \%AddTypes;
2806 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002807}
2808
2809sub addMissedTypes_Post()
2810{
2811 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2812 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002813 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2814 {
2815 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2816 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2817 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2818 }
2819 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002820 }
2821}
2822
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002823sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002824{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002825 my $TypeId = $_[0];
2826 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2827 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002828 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002829 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002830 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002831}
2832
2833sub getArraySize($$)
2834{
2835 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002836 if(my $Size = getSize($TypeId))
2837 {
2838 my $Elems = $Size/$BYTE_SIZE;
2839 while($BaseName=~s/\s*\[(\d+)\]//) {
2840 $Elems/=$1;
2841 }
2842 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2843 {
2844 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2845 $Elems/=$BasicSize;
2846 }
2847 }
2848 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002849 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002850 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002851}
2852
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002853sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002854{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002855 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002856 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002857 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2858 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002859 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002860 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2861 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2862 if(not $NodeType)
2863 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002864 return ();
2865 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002866 if($NodeType eq "tree_vec")
2867 {
2868 if($Pos!=$#Positions)
2869 { # select last vector of parameters ( ns<P1>::type<P2> )
2870 next;
2871 }
2872 }
2873 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2874 foreach my $P (@Params)
2875 {
2876 if($P eq "") {
2877 return ();
2878 }
2879 elsif($P ne "\@skip\@") {
2880 @TmplParams = (@TmplParams, $P);
2881 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002882 }
2883 }
2884 return @TmplParams;
2885}
2886
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002887sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002888{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002889 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002890 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002891 if(defined $TypeInfo{$Version}{$TypeId}
2892 and $TypeInfo{$Version}{$TypeId}{"Name"})
2893 { # already created
2894 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002895 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002896 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2897 { # incomplete type
2898 return ();
2899 }
2900 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2901
2902 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002903 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002904
2905 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2906 {
2907 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2908 {
2909 if($Info=~/qual[ ]*:/)
2910 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002911 my $NewId = ++$MAX_ID;
2912
2913 $MissedBase{$Version}{$TypeId} = "$NewId";
2914 $MissedBase_R{$Version}{$NewId} = $TypeId;
2915 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2916 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002917 }
2918 }
2919 $TypeAttr{"Type"} = "Typedef";
2920 }
2921 else {
2922 $TypeAttr{"Type"} = getTypeType($TypeId);
2923 }
2924
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002925 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2926 {
2927 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2928 { # local code
2929 return ();
2930 }
2931 }
2932
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002933 if($TypeAttr{"Type"} eq "Unknown") {
2934 return ();
2935 }
2936 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2937 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002938 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002939 if(my $TName = $TypeAttr{"Name"})
2940 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002941 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002942 $TName_Tid{$Version}{$TName} = $TypeId;
2943 return %TypeAttr;
2944 }
2945 else {
2946 return ();
2947 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002948 }
2949 elsif($TypeAttr{"Type"} eq "Array")
2950 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002951 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2952 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002953 return ();
2954 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002955 if(my $Algn = getAlgn($TypeId)) {
2956 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2957 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002958 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002959 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002960 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002961 if(not $BTAttr{"Name"}) {
2962 return ();
2963 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002964 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002965 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002966 if(my $Size = getSize($TypeId)) {
2967 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2968 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002969 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002970 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2971 }
2972 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002973 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002974 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002975 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002976 else
2977 {
2978 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002979 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002980 $TypeAttr{"Name"} = $1."[]".$2;
2981 }
2982 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002983 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002984 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002985 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002986 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002987 if($BTAttr{"Header"}) {
2988 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002989 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002990 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002991 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2992 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002993 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002994 return ();
2995 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002996 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002997 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002998 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002999 if($TypeAttr{"Name"})
3000 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003001 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003002
3003 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
3004 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003005 { # NOTE: register only one int: with built-in decl
3006 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3007 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3008 }
3009 }
3010 return %TypeAttr;
3011 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003012 else {
3013 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003014 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003015 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003016 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
3017 {
3018 %TypeAttr = getTrivialTypeAttr($TypeId);
3019 if($TypeAttr{"Name"})
3020 {
3021 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
3022 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3023 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3024 }
3025 return %TypeAttr;
3026 }
3027 else {
3028 return ();
3029 }
3030 }
3031 elsif($TypeAttr{"Type"} eq "SizeOf")
3032 {
3033 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
3034 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
3035 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
3036 if($TypeAttr{"Name"})
3037 {
3038 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
3039 return %TypeAttr;
3040 }
3041 else {
3042 return ();
3043 }
3044 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003045 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003046 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003047 my ($BTid, $BTSpec) = selectBaseType($TypeId);
3048 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003049 return ();
3050 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003051 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003052 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003053 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003054 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003055 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003056 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003057 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003058 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003059 }
3060 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003061 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003062 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003063 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003064 return ();
3065 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003066 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003067 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003068 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003069 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003070 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003071 }
3072 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003073 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003074 {
3075 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003076 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003077 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003078 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003079 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
3080 }
3081 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003082 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003083 }
3084 }
3085 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003086 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003087 }
3088 if($TypeAttr{"Type"} eq "Typedef")
3089 {
3090 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003091
3092 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
3093 return ();
3094 }
3095
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003096 if(isAnon($TypeAttr{"Name"}))
3097 { # anon typedef to anon type: ._N
3098 return ();
3099 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003100
3101 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
3102 { # artificial typedef of "struct X" to "X"
3103 $TypeAttr{"Artificial"} = 1;
3104 }
3105
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003106 if(my $NS = getNameSpace($TypeDeclId))
3107 {
3108 my $TypeName = $TypeAttr{"Name"};
3109 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
3110 { # "some_type" is the typedef to "struct some_type" in C++
3111 if($3) {
3112 $TypeAttr{"Name"} = $3."::".$TypeName;
3113 }
3114 }
3115 else
3116 {
3117 $TypeAttr{"NameSpace"} = $NS;
3118 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003119
3120 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
3121 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
3122 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003123 if($BTAttr{"NameSpace"}
3124 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003125 { # types like "std::fpos<__mbstate_t>" are
3126 # not covered by typedefs in the TU dump
3127 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003128 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3129 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003130 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003131 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003132 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003133 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003134 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003135 }
3136 }
3137 }
3138 }
3139 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003140 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003141 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003142 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003143 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3144 { # typedef int*const TYPEDEF; // first
3145 # int foo(TYPEDEF p); // const is optimized out
3146 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3147 if($BTAttr{"Name"}=~/</)
3148 {
3149 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3150 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3151 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003152 }
3153 }
3154 }
3155 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3156 }
3157 if(not $TypeAttr{"Size"})
3158 {
3159 if($TypeAttr{"Type"} eq "Pointer") {
3160 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3161 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003162 elsif($BTAttr{"Size"}) {
3163 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003164 }
3165 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003166 if(my $Algn = getAlgn($TypeId)) {
3167 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3168 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003169 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003170 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3171 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003172 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003173 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003174 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003175 { # typedef to "class Class"
3176 # should not be registered in TName_Tid
3177 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3178 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3179 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003180 }
3181 return %TypeAttr;
3182 }
3183}
3184
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003185sub getTreeVec($)
3186{
3187 my %Vector = ();
3188 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3189 {
3190 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3191 { # string length is N-1 because of the null terminator
3192 $Vector{$1} = $2;
3193 }
3194 }
3195 return \%Vector;
3196}
3197
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003198sub get_TemplateParam($$)
3199{
3200 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003201 return () if(not $Type_Id);
3202 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3203 return () if(not $NodeType);
3204 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003205 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003206 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003207 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003208 my $Num = getNodeIntCst($Type_Id);
3209 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003210 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003211 }
3212 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003213 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003214 }
3215 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003216 elsif($NodeType eq "string_cst") {
3217 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003218 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003219 elsif($NodeType eq "tree_vec")
3220 {
3221 my $Vector = getTreeVec($Type_Id);
3222 my @Params = ();
3223 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3224 {
3225 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3226 push(@Params, $P2);
3227 }
3228 }
3229 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003230 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003231 elsif($NodeType eq "parm_decl")
3232 {
3233 (getNameByInfo($Type_Id));
3234 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003235 else
3236 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003237 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003238 my $PName = $ParamAttr{"Name"};
3239 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003240 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003241 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003242 if($PName=~/\>/)
3243 {
3244 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003245 $PName = $Cover;
3246 }
3247 }
3248 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003249 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003250 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3251 # template<typename _Key, typename _Compare = std::less<_Key>
3252 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3253 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3254 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3255 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003256 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003257 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003258 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003259 }
3260}
3261
3262sub cover_stdcxx_typedef($)
3263{
3264 my $TypeName = $_[0];
3265 if(my @Covers = sort {length($a)<=>length($b)}
3266 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3267 { # take the shortest typedef
3268 # FIXME: there may be more than
3269 # one typedefs to the same type
3270 return $Covers[0];
3271 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003272 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003273 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3274 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3275 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003276 if(my $Cover = $Covers[0])
3277 {
3278 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3279 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3280 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003281 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003282 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003283}
3284
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003285sub getNodeIntCst($)
3286{
3287 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003288 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003289 if($EnumMembName_Id{$Version}{$CstId}) {
3290 return $EnumMembName_Id{$Version}{$CstId};
3291 }
3292 elsif((my $Value = getTreeValue($CstId)) ne "")
3293 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003294 if($Value eq "0")
3295 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003296 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003297 return "false";
3298 }
3299 else {
3300 return "0";
3301 }
3302 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003303 elsif($Value eq "1")
3304 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003305 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003306 return "true";
3307 }
3308 else {
3309 return "1";
3310 }
3311 }
3312 else {
3313 return $Value;
3314 }
3315 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003316 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003317}
3318
3319sub getNodeStrCst($)
3320{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003321 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3322 {
3323 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003324 {
3325 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3326 { # string length is N-1 because of the null terminator
3327 return substr($1, 0, $2-1);
3328 }
3329 else
3330 { # identifier_node
3331 return substr($1, 0, $2);
3332 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003334 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003335 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003336}
3337
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003338sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003339{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003340 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003341 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3342 if($Type eq "FieldPtr") {
3343 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3344 }
3345 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3346 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003347 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003348 if($Type eq "MethodPtr")
3349 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003350 if(my $Size = getSize($TypeId))
3351 {
3352 $Size/=$BYTE_SIZE;
3353 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003354 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003355 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003356 if(my $Algn = getAlgn($TypeId)) {
3357 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003359 # Return
3360 if($Type eq "FieldPtr")
3361 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003362 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003363 if($ReturnAttr{"Name"}) {
3364 $MemPtrName .= $ReturnAttr{"Name"};
3365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003366 $TypeAttr{"Return"} = $PtrId;
3367 }
3368 else
3369 {
3370 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3371 {
3372 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003373 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3374 if(not $ReturnAttr{"Name"})
3375 { # templates
3376 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003377 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003378 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003379 $TypeAttr{"Return"} = $ReturnTypeId;
3380 }
3381 }
3382 # Class
3383 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3384 {
3385 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003386 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003387 if($Class{"Name"}) {
3388 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3389 }
3390 else {
3391 $MemPtrName .= " (*)";
3392 }
3393 }
3394 else {
3395 $MemPtrName .= " (*)";
3396 }
3397 # Parameters
3398 if($Type eq "FuncPtr"
3399 or $Type eq "MethodPtr")
3400 {
3401 my @ParamTypeName = ();
3402 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3403 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003404 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003405 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003406 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003407 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003408 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3409 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003410 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003411 my $PTypeId = $1;
3412 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003413 if(not $ParamAttr{"Name"})
3414 { # templates (template_type_parm), etc.
3415 return ();
3416 }
3417 if($ParamAttr{"Name"} eq "void") {
3418 last;
3419 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003420 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003421 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003422 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003423 push(@ParamTypeName, $ParamAttr{"Name"});
3424 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003425 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3426 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003427 }
3428 else {
3429 last;
3430 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003431 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003432 else {
3433 last;
3434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003435 }
3436 }
3437 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3438 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003439 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003440 return %TypeAttr;
3441}
3442
3443sub getTreeTypeName($)
3444{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003445 my $TypeId = $_[0];
3446 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003447 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003448 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003449 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003450 if(my $Name = getNameByInfo($TypeId))
3451 { # bit_size_type
3452 return $Name;
3453 }
3454 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003455 return "unsigned int";
3456 }
3457 else {
3458 return "int";
3459 }
3460 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003461 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003462 return getNameByInfo($1);
3463 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003464 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003465 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003466}
3467
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003468sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003469{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003470 my $Ptd = pointTo($_[0]);
3471 return 0 if(not $Ptd);
3472 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003473 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003474 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3475 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003476 }
3477 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003478 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3479 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003480 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003481 if($InfoT1 eq "pointer_type"
3482 and $InfoT2 eq "function_type") {
3483 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003484 }
3485 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003486 return 0;
3487}
3488
3489sub isMethodPtr($)
3490{
3491 my $Ptd = pointTo($_[0]);
3492 return 0 if(not $Ptd);
3493 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3494 {
3495 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3496 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3497 and $Info=~/ ptrmem /) {
3498 return 1;
3499 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003500 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003501 return 0;
3502}
3503
3504sub isFieldPtr($)
3505{
3506 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3507 {
3508 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3509 and $Info=~/ ptrmem /) {
3510 return 1;
3511 }
3512 }
3513 return 0;
3514}
3515
3516sub pointTo($)
3517{
3518 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3519 {
3520 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3521 return $1;
3522 }
3523 }
3524 return "";
3525}
3526
3527sub getTypeTypeByTypeId($)
3528{
3529 my $TypeId = $_[0];
3530 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3531 {
3532 my $NType = $NodeType{$TType};
3533 if($NType eq "Intrinsic") {
3534 return $NType;
3535 }
3536 elsif(isFuncPtr($TypeId)) {
3537 return "FuncPtr";
3538 }
3539 elsif(isMethodPtr($TypeId)) {
3540 return "MethodPtr";
3541 }
3542 elsif(isFieldPtr($TypeId)) {
3543 return "FieldPtr";
3544 }
3545 elsif($NType ne "Other") {
3546 return $NType;
3547 }
3548 }
3549 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003550}
3551
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003552my %UnQual = (
3553 "r"=>"restrict",
3554 "v"=>"volatile",
3555 "c"=>"const",
3556 "cv"=>"const volatile"
3557);
3558
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003559sub getQual($)
3560{
3561 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003562 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3563 {
3564 my ($Qual, $To) = ();
3565 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3566 $Qual = $UnQual{$1};
3567 }
3568 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3569 $To = $1;
3570 }
3571 if($Qual and $To) {
3572 return ($Qual, $To);
3573 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003574 }
3575 return ();
3576}
3577
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003578sub getQualType($)
3579{
3580 if($_[0] eq "const volatile") {
3581 return "ConstVolatile";
3582 }
3583 return ucfirst($_[0]);
3584}
3585
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003586sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003587{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003588 my $TypeId = $_[0];
3589 my $TypeDeclId = getTypeDeclId($TypeId);
3590 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003591 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003592 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3593 return "Typedef";
3594 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003595 }
3596 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3597 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003598 if(($Qual or $To) and $TypeDeclId
3599 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003600 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003601 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003602 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003603 elsif(not $MissedBase_R{$Version}{$TypeId}
3604 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003605 return "Typedef";
3606 }
3607 elsif($Qual)
3608 { # qualified types
3609 return getQualType($Qual);
3610 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003611
3612 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3613 { # typedef struct { ... } name
3614 $TypeTypedef{$Version}{$TypeId} = $1;
3615 }
3616
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003617 my $TypeType = getTypeTypeByTypeId($TypeId);
3618 if($TypeType eq "Struct")
3619 {
3620 if($TypeDeclId
3621 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3622 return "Template";
3623 }
3624 }
3625 return $TypeType;
3626}
3627
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003628sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003629{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003630 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003631 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003632 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3633 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3634 return 0;
3635 }
3636 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3637 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003638 if(my $TDid = getTypeDeclId($_[0]))
3639 {
3640 if(getTypeId($TDid) eq $_[0]
3641 and getNameByInfo($TDid))
3642 {
3643 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3644 return $1;
3645 }
3646 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003647 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003648 }
3649 }
3650 return 0;
3651}
3652
3653sub selectBaseType($)
3654{
3655 my $TypeId = $_[0];
3656 if(defined $MissedTypedef{$Version}{$TypeId})
3657 { # add missed typedefs
3658 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3659 return ($TypeId, "");
3660 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003661 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003662 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3663 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003664
3665 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3666 my $MB = $MissedBase{$Version}{$TypeId};
3667
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003668 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003669 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003670 and (getTypeId($1) ne $TypeId)
3671 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003672 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003673 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003674 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003675 elsif($MB)
3676 { # add base
3677 return ($MB, "");
3678 }
3679 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003680 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003681 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003682 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003683 elsif($Qual or $To)
3684 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003685 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003686 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003687 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003688 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003689 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003690 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003691 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003692 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003693 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003694 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003695 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003696 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003697 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003698 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003699 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003700 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003701 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003702 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003704 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003705
3706 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003707}
3708
3709sub getSymbolInfo_All()
3710{
3711 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3712 { # reverse order
3713 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003714 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003715 }
3716 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003717
3718 if($ADD_TMPL_INSTANCES)
3719 {
3720 # templates
3721 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3722 {
3723 my %Map = ();
3724
3725 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3726 {
3727 if(defined $TemplateMap{$Version}{$ClassId})
3728 {
3729 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3730 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3731 }
3732 }
3733 }
3734
3735 if(defined $TemplateMap{$Version}{$Sid})
3736 {
3737 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3738 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3739 }
3740 }
3741
3742 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3743 {
3744 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3745 {
3746 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3747 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3748 }
3749 }
3750 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3751 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3752 }
3753 }
3754 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003755}
3756
3757sub getVarInfo_All()
3758{
3759 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3760 { # reverse order
3761 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003762 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003763 }
3764 }
3765}
3766
3767sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003768 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003769}
3770
3771sub getVarInfo($)
3772{
3773 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003774 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003775 {
3776 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3777 if($NSInfoType and $NSInfoType eq "function_decl") {
3778 return;
3779 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003780 }
3781 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3782 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3783 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3784 delete($SymbolInfo{$Version}{$InfoId});
3785 return;
3786 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003787 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003788 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003789 delete($SymbolInfo{$Version}{$InfoId});
3790 return;
3791 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003792 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3793 delete($SymbolInfo{$Version}{$InfoId});
3794 return;
3795 }
3796 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003797 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3798 {
3799 if($OSgroup eq "windows")
3800 { # cut the offset
3801 $MnglName=~s/\@\d+\Z//g;
3802 }
3803 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3804 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003805 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003806 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003807 { # validate mangled name
3808 delete($SymbolInfo{$Version}{$InfoId});
3809 return;
3810 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003811 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003812 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003813 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003814 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003815 }
3816 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3817 { # non-public global data
3818 delete($SymbolInfo{$Version}{$InfoId});
3819 return;
3820 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003821 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003822 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003823 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003824 if(not defined $TypeInfo{$Version}{$Rid}
3825 or not $TypeInfo{$Version}{$Rid}{"Name"})
3826 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003827 delete($SymbolInfo{$Version}{$InfoId});
3828 return;
3829 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003830 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3831 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003832 if(defined $Val) {
3833 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3834 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003835 }
3836 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003837 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3838 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003839 if(not defined $TypeInfo{$Version}{$ClassId}
3840 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3841 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003842 delete($SymbolInfo{$Version}{$InfoId});
3843 return;
3844 }
3845 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003846 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3847 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003848 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003849 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003850 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003851 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003852 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003853 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003854 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003855 if(not $CheckHeadersOnly)
3856 {
3857 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3858 {
3859 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3860 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3861 {
3862 if(link_symbol($ShortName, $Version, "-Deps"))
3863 { # "const" global data is mangled as _ZL... in the TU dump
3864 # but not mangled when compiling a C shared library
3865 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3866 }
3867 }
3868 }
3869 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003870 if($COMMON_LANGUAGE{$Version} eq "C++")
3871 {
3872 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3873 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003874 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003875 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3876 }
3877 }
3878 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3879 { # try to mangle symbol (link with libraries)
3880 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3881 }
3882 if($OStarget eq "windows")
3883 {
3884 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3885 { # link MS C++ symbols from library with GCC symbols from headers
3886 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3887 }
3888 }
3889 }
3890 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3891 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3892 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003893 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3894 {
3895 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3896 { # non-target symbols
3897 delete($SymbolInfo{$Version}{$InfoId});
3898 return;
3899 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003900 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003901 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3902 {
3903 if(defined $MissedTypedef{$Version}{$Rid})
3904 {
3905 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3906 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3907 }
3908 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003909 }
3910 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003911 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003912 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3913 }
3914 if($ShortName=~/\A(_Z|\?)/) {
3915 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3916 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003917
3918 if($ExtraDump) {
3919 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3920 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003921}
3922
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003923sub isConstType($$)
3924{
3925 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003926 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003927 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003928 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003929 }
3930 return ($Base{"Type"} eq "Const");
3931}
3932
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003933sub getTrivialName($$)
3934{
3935 my ($TypeInfoId, $TypeId) = @_;
3936 my %TypeAttr = ();
3937 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3938 if(not $TypeAttr{"Name"}) {
3939 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3940 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003941 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003942 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003943 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003944 if(isAnon($TypeAttr{"Name"}))
3945 {
3946 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003947 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003948 { # searching for a first not anon scope
3949 if($NSId eq $NameSpaceId) {
3950 last;
3951 }
3952 else
3953 {
3954 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3955 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003956 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003957 last;
3958 }
3959 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003960 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003961 }
3962 }
3963 else
3964 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003965 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003966 {
3967 if($NameSpaceId ne $TypeId) {
3968 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3969 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003970 }
3971 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003972 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003973 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3974 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003975 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003976 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003977 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003978 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003979 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003980 if($TypeAttr{"NameSpace"}) {
3981 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003983 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003984 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3985 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003986 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003987 if(my @TParams = getTParams($TypeId, "Type")) {
3988 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3989 }
3990 else {
3991 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003993 }
3994 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3995}
3996
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003997sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003998{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003999 my $TypeId = $_[0];
4000 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004001
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004002 my %TypeAttr = ();
4003
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004004 if($TemplateDecl{$Version}{$TypeId})
4005 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004006 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004007 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004008
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004009 setTypeAccess($TypeId, \%TypeAttr);
4010 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
4011 if(isBuiltIn($TypeAttr{"Header"}))
4012 {
4013 delete($TypeAttr{"Header"});
4014 delete($TypeAttr{"Line"});
4015 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04004016
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004017 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004018 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
4019 if(not $TypeAttr{"Name"}) {
4020 return ();
4021 }
4022 if(not $TypeAttr{"NameSpace"}) {
4023 delete($TypeAttr{"NameSpace"});
4024 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004025
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04004026 if($TypeAttr{"Type"} eq "Intrinsic")
4027 {
4028 if(defined $TypeAttr{"Header"})
4029 {
4030 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
4031 { # support for SUSE 11.2
4032 # integer_type has srcp dump{1-2}.i
4033 delete($TypeAttr{"Header"});
4034 }
4035 }
4036 }
4037
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004038 my $Tmpl = undef;
4039
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004040 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004041 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004042 $Tmpl = $BasicTemplate{$Version}{$TypeId};
4043
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004044 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004045 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004046 foreach my $Pos (0 .. $#TParams)
4047 {
4048 my $Val = $TParams[$Pos];
4049 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
4050
4051 if(not defined $TypeAttr{"Template"})
4052 {
4053 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
4054
4055 if($Base{"Type"} eq "TemplateParam"
4056 or defined $Base{"Template"}) {
4057 $TypeAttr{"Template"} = 1;
4058 }
4059 }
4060
4061 if($Tmpl)
4062 {
4063 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
4064 {
4065 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
4066
4067 if($Val eq $Arg) {
4068 $TypeAttr{"Template"} = 1;
4069 }
4070 }
4071 }
4072 }
4073
4074 if($Tmpl)
4075 {
4076 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
4077 {
4078 if($Pos>$#TParams)
4079 {
4080 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
4081 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
4082 }
4083 }
4084 }
4085 }
4086
4087 if($ADD_TMPL_INSTANCES)
4088 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004089 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004090 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004091 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004092 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004093 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004094 {
4095 if(my $Flds = getTreeAttr_Flds($MainInst)) {
4096 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
4097 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004098 }
4099 if(not getTreeAttr_Binf($TypeId))
4100 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004101 if(my $Binf = getTreeAttr_Binf($MainInst)) {
4102 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
4103 }
4104 }
4105 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004106 }
4107 }
4108 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004109
4110 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
4111
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004112 if(my $Size = getSize($TypeId))
4113 {
4114 $Size = $Size/$BYTE_SIZE;
4115 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004116 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004117 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004118 {
4119 if($ExtraDump)
4120 {
4121 if(not defined $TypeAttr{"Memb"}
4122 and not $Tmpl)
4123 { # declaration only
4124 $TypeAttr{"Forward"} = 1;
4125 }
4126 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004127 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004128
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004129 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004130 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004131 {
4132 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004133 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004134 }
4135 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004136 or $TypeAttr{"Type"} eq "Class")
4137 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004138 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004139 if($Skip) {
4140 return ();
4141 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004142 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004143 if(my $Algn = getAlgn($TypeId)) {
4144 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4145 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004146 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004147
4148 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4149 {
4150 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004151 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004152 {
4153 if(not isAnon($TypeAttr{"Name"})) {
4154 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4155 }
4156 }
4157 }
4158
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004159 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004160 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4161 {
4162 my @Entries = split(/\n/, $VTable);
4163 foreach (1 .. $#Entries)
4164 {
4165 my $Entry = $Entries[$_];
4166 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004167 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004168 }
4169 }
4170 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004171
4172 if($TypeAttr{"Type"} eq "Enum")
4173 {
4174 if(not $TypeAttr{"NameSpace"})
4175 {
4176 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4177 {
4178 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004179 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004180 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004181 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004182 "Header"=>$TypeAttr{"Header"}
4183 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004184 if(isAnon($TypeAttr{"Name"}))
4185 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004186 if($ExtraDump
4187 or is_target_header($TypeAttr{"Header"}, $Version))
4188 {
4189 %{$Constants{$Version}{$MName}} = (
4190 "Value" => $MVal,
4191 "Header" => $TypeAttr{"Header"}
4192 );
4193 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004194 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004195 }
4196 }
4197 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004198 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004199 {
4200 if(defined $TypedefToAnon{$TypeId}) {
4201 $TypeAttr{"AnonTypedef"} = 1;
4202 }
4203 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004204
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004205 return %TypeAttr;
4206}
4207
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004208sub simplifyVTable($)
4209{
4210 my $Content = $_[0];
4211 if($Content=~s/ \[with (.+)]//)
4212 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4213 if(my @Elems = separate_Params($1, 0, 0))
4214 {
4215 foreach my $Elem (@Elems)
4216 {
4217 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4218 {
4219 my ($Arg, $Val) = ($1, $2);
4220
4221 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4222 $Content=~s/,\s*$Arg\b//g;
4223 }
4224 else {
4225 $Content=~s/\b$Arg\b/$Val/g;
4226 }
4227 }
4228 }
4229 }
4230 }
4231
4232 return $Content;
4233}
4234
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004235sub detect_lang($)
4236{
4237 my $TypeId = $_[0];
4238 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004239 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004240 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004241 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4242 }
4243 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004244 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004245 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004246 while($Fncs)
4247 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004248 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004249 return 1;
4250 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004251 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004252 }
4253 }
4254 return 0;
4255}
4256
4257sub setSpec($$)
4258{
4259 my ($TypeId, $TypeAttr) = @_;
4260 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4261 if($Info=~/\s+spec\s+/) {
4262 $TypeAttr->{"Spec"} = 1;
4263 }
4264}
4265
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004266sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004267{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004268 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004269 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004270 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004271 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004272 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004273 my $Pos = 0;
4274 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4275 {
4276 my ($Access, $BInfoId) = ($1, $2);
4277 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004278
4279 if($ClassId==$TypeId)
4280 { # class A<N>:public A<N-1>
4281 next;
4282 }
4283
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004284 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4285 if(not $CType or $CType eq "template_type_parm"
4286 or $CType eq "typename_type")
4287 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004288 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004289 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004290 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004291 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004292 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4293 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004294 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004295 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4296 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004297 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004298 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004299 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004300 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4301 }
4302 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004303 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004304 }
4305 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004306 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004307}
4308
4309sub getBinfClassId($)
4310{
4311 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4312 $Info=~/type[ ]*:[ ]*@(\d+) /;
4313 return $1;
4314}
4315
4316sub unmangledFormat($$)
4317{
4318 my ($Name, $LibVersion) = @_;
4319 $Name = uncover_typedefs($Name, $LibVersion);
4320 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4321 $Name=~s/\(\w+\)(\d)/$1/;
4322 return $Name;
4323}
4324
4325sub modelUnmangled($$)
4326{
4327 my ($InfoId, $Compiler) = @_;
4328 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4329 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4330 }
4331 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4332 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4333 $PureSignature = "~".$PureSignature;
4334 }
4335 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4336 {
4337 my (@Params, @ParamTypes) = ();
4338 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4339 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4340 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4341 }
4342 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4343 { # checking parameters
4344 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004345 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004346 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004347 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004348
4349 if($PName eq "this"
4350 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4351 {
4352 next;
4353 }
4354
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004355 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004356 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004357 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004358 }
4359 @ParamTypes = (@ParamTypes, $PTName);
4360 }
4361 if(@ParamTypes) {
4362 $PureSignature .= "(".join(", ", @ParamTypes).")";
4363 }
4364 else
4365 {
4366 if($Compiler eq "MSVC")
4367 {
4368 $PureSignature .= "(void)";
4369 }
4370 else
4371 { # GCC
4372 $PureSignature .= "()";
4373 }
4374 }
4375 $PureSignature = delete_keywords($PureSignature);
4376 }
4377 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4378 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004379 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004380 $PureSignature = $ClassName."::".$PureSignature;
4381 }
4382 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4383 $PureSignature = $NS."::".$PureSignature;
4384 }
4385 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4386 $PureSignature .= " const";
4387 }
4388 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4389 $PureSignature .= " volatile";
4390 }
4391 my $ShowReturn = 0;
4392 if($Compiler eq "MSVC"
4393 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4394 {
4395 $ShowReturn=1;
4396 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004397 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4398 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004399 {
4400 $ShowReturn=1;
4401 }
4402 if($ShowReturn)
4403 { # mangled names for template function specializations include return value
4404 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4405 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004406 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004407 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4408 $PureSignature = $ReturnName." ".$PureSignature;
4409 }
4410 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004411 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004412}
4413
4414sub mangle_symbol($$$)
4415{ # mangling for simple methods
4416 # see gcc-4.6.0/gcc/cp/mangle.c
4417 my ($InfoId, $LibVersion, $Compiler) = @_;
4418 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4419 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4420 }
4421 my $Mangled = "";
4422 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004423 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004424 }
4425 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004426 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004427 }
4428 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4429}
4430
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004431sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004432{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004433 my ($InfoId, $LibVersion) = @_;
4434 return "";
4435}
4436
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004437sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004438{ # see gcc-4.6.0/gcc/cp/mangle.c
4439 my ($InfoId, $LibVersion) = @_;
4440 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004441 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004442 my %Repl = ();# SN_ replacements
4443 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4444 {
4445 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4446 if($MangledClass!~/\AN/) {
4447 $MangledClass = "N".$MangledClass;
4448 }
4449 else {
4450 $MangledClass=~s/E\Z//;
4451 }
4452 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4453 $MangledClass=~s/\AN/NV/;
4454 }
4455 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4456 $MangledClass=~s/\AN/NK/;
4457 }
4458 $Mangled .= $MangledClass;
4459 }
4460 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4461 { # mangled by name due to the absence of structured info
4462 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4463 if($MangledNS!~/\AN/) {
4464 $MangledNS = "N".$MangledNS;
4465 }
4466 else {
4467 $MangledNS=~s/E\Z//;
4468 }
4469 $Mangled .= $MangledNS;
4470 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004471 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004472 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004473 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004474 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004475 foreach (@TPos) {
4476 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4477 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004478 }
4479 elsif($TmplParams)
4480 { # remangling mode
4481 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004482 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004483 }
4484 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4485 $Mangled .= "C1";
4486 }
4487 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4488 $Mangled .= "D0";
4489 }
4490 elsif($ShortName)
4491 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004492 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4493 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004494 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004495 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004496 { # "const" global data is mangled as _ZL...
4497 $Mangled .= "L";
4498 }
4499 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004500 if($ShortName=~/\Aoperator(\W.*)\Z/)
4501 {
4502 my $Op = $1;
4503 $Op=~s/\A[ ]+//g;
4504 if(my $OpMngl = $OperatorMangling{$Op}) {
4505 $Mangled .= $OpMngl;
4506 }
4507 else { # conversion operator
4508 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4509 }
4510 }
4511 else {
4512 $Mangled .= length($ShortName).$ShortName;
4513 }
4514 if(@TParams)
4515 { # templates
4516 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004517 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004518 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4519 }
4520 $Mangled .= "E";
4521 }
4522 if(not $ClassId and @TParams) {
4523 add_substitution($ShortName, \%Repl, 0);
4524 }
4525 }
4526 if($ClassId or $NameSpace) {
4527 $Mangled .= "E";
4528 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004529 if(@TParams)
4530 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004531 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004532 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4533 }
4534 }
4535 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4536 {
4537 my @Params = ();
4538 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4539 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4540 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4541 }
4542 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4543 { # checking parameters
4544 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4545 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4546 }
4547 if(not @Params) {
4548 $Mangled .= "v";
4549 }
4550 }
4551 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4552 $Mangled = write_stdcxx_substitution($Mangled);
4553 if($Mangled eq "_Z") {
4554 return "";
4555 }
4556 return $Mangled;
4557}
4558
4559sub correct_incharge($$$)
4560{
4561 my ($InfoId, $LibVersion, $Mangled) = @_;
4562 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4563 {
4564 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004565 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004566 }
4567 }
4568 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4569 {
4570 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004571 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004572 }
4573 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004574 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004575 }
4576 }
4577 return $Mangled;
4578}
4579
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004580sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004581{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004582 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004583 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004584 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004585 return $Name;
4586 }
4587 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004588 while(my $CPos = find_center($TParams, "<"))
4589 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004590 $TParams = substr($TParams, $CPos);
4591 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004592 if($TParams=~s/\A<(.+)>\Z/$1/) {
4593 $Name=~s/<\Q$TParams\E>\Z//;
4594 }
4595 else
4596 { # error
4597 $TParams = "";
4598 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004599 return ($Name, $TParams);
4600}
4601
4602sub get_sub_ns($)
4603{
4604 my $Name = $_[0];
4605 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004606 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004607 {
4608 push(@NS, substr($Name, 0, $CPos));
4609 $Name = substr($Name, $CPos);
4610 $Name=~s/\A:://;
4611 }
4612 return (join("::", @NS), $Name);
4613}
4614
4615sub mangle_ns($$$)
4616{
4617 my ($Name, $LibVersion, $Repl) = @_;
4618 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4619 {
4620 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4621 $Mangled=~s/\AN(.+)E\Z/$1/;
4622 return $Mangled;
4623
4624 }
4625 else
4626 {
4627 my ($MangledNS, $SubNS) = ("", "");
4628 ($SubNS, $Name) = get_sub_ns($Name);
4629 if($SubNS) {
4630 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4631 }
4632 $MangledNS .= length($Name).$Name;
4633 add_substitution($MangledNS, $Repl, 0);
4634 return $MangledNS;
4635 }
4636}
4637
4638sub mangle_param($$$)
4639{
4640 my ($PTid, $LibVersion, $Repl) = @_;
4641 my ($MPrefix, $Mangled) = ("", "");
4642 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004643 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004644 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004645 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004646 if(not $BaseType_Name) {
4647 return "";
4648 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004649 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004650 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004651 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4652 while($Suffix=~/(&|\*|const)\Z/)
4653 {
4654 if($Suffix=~s/[ ]*&\Z//) {
4655 $MPrefix .= "R";
4656 }
4657 if($Suffix=~s/[ ]*\*\Z//) {
4658 $MPrefix .= "P";
4659 }
4660 if($Suffix=~s/[ ]*const\Z//)
4661 {
4662 if($MPrefix=~/R|P/
4663 or $Suffix=~/&|\*/) {
4664 $MPrefix .= "K";
4665 }
4666 }
4667 if($Suffix=~s/[ ]*volatile\Z//) {
4668 $MPrefix .= "V";
4669 }
4670 #if($Suffix=~s/[ ]*restrict\Z//) {
4671 #$MPrefix .= "r";
4672 #}
4673 }
4674 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4675 $Mangled .= $Token;
4676 }
4677 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4678 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004679 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004680 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004681 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004682 foreach (@TPos) {
4683 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4684 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004685 }
4686 elsif($TmplParams)
4687 { # remangling mode
4688 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004689 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004690 }
4691 my $MangledNS = "";
4692 my ($SubNS, $SName) = get_sub_ns($ShortName);
4693 if($SubNS) {
4694 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4695 }
4696 $MangledNS .= length($SName).$SName;
4697 if(@TParams) {
4698 add_substitution($MangledNS, $Repl, 0);
4699 }
4700 $Mangled .= "N".$MangledNS;
4701 if(@TParams)
4702 { # templates
4703 $Mangled .= "I";
4704 foreach my $TParam (@TParams) {
4705 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4706 }
4707 $Mangled .= "E";
4708 }
4709 $Mangled .= "E";
4710 }
4711 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4712 {
4713 if($BaseType{"Type"} eq "MethodPtr") {
4714 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4715 }
4716 else {
4717 $Mangled .= "PF";
4718 }
4719 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4720 my @Params = keys(%{$BaseType{"Param"}});
4721 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4722 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4723 }
4724 if(not @Params) {
4725 $Mangled .= "v";
4726 }
4727 $Mangled .= "E";
4728 }
4729 elsif($BaseType{"Type"} eq "FieldPtr")
4730 {
4731 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4732 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4733 }
4734 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4735 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4736 {
4737 if($Mangled eq $Optimized)
4738 {
4739 if($ShortName!~/::/)
4740 { # remove "N ... E"
4741 if($MPrefix) {
4742 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4743 }
4744 else {
4745 $Mangled=~s/\AN(.+)E\Z/$1/g;
4746 }
4747 }
4748 }
4749 else {
4750 $Mangled = $Optimized;
4751 }
4752 }
4753 add_substitution($Mangled, $Repl, 1);
4754 return $Mangled;
4755}
4756
4757sub mangle_template_param($$$)
4758{ # types + literals
4759 my ($TParam, $LibVersion, $Repl) = @_;
4760 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4761 return mangle_param($TPTid, $LibVersion, $Repl);
4762 }
4763 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4764 { # class_name<1u>::method(...)
4765 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4766 }
4767 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4768 { # class_name<(signed char)1>::method(...)
4769 return "L".$IntrinsicMangling{$1}.$2."E";
4770 }
4771 elsif($TParam eq "true")
4772 { # class_name<true>::method(...)
4773 return "Lb1E";
4774 }
4775 elsif($TParam eq "false")
4776 { # class_name<true>::method(...)
4777 return "Lb0E";
4778 }
4779 else { # internal error
4780 return length($TParam).$TParam;
4781 }
4782}
4783
4784sub add_substitution($$$)
4785{
4786 my ($Value, $Repl, $Rec) = @_;
4787 if($Rec)
4788 { # subtypes
4789 my @Subs = ($Value);
4790 while($Value=~s/\A(R|P|K)//) {
4791 push(@Subs, $Value);
4792 }
4793 foreach (reverse(@Subs)) {
4794 add_substitution($_, $Repl, 0);
4795 }
4796 return;
4797 }
4798 return if($Value=~/\AS(\d*)_\Z/);
4799 $Value=~s/\AN(.+)E\Z/$1/g;
4800 return if(defined $Repl->{$Value});
4801 return if(length($Value)<=1);
4802 return if($StdcxxMangling{$Value});
4803 # check for duplicates
4804 my $Base = $Value;
4805 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4806 {
4807 my $Num = $Repl->{$Type};
4808 my $Replace = macro_mangle($Num);
4809 $Base=~s/\Q$Replace\E/$Type/;
4810 }
4811 if(my $OldNum = $Repl->{$Base})
4812 {
4813 $Repl->{$Value} = $OldNum;
4814 return;
4815 }
4816 my @Repls = sort {$b<=>$a} values(%{$Repl});
4817 if(@Repls) {
4818 $Repl->{$Value} = $Repls[0]+1;
4819 }
4820 else {
4821 $Repl->{$Value} = -1;
4822 }
4823 # register duplicates
4824 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004825 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004826 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4827 {
4828 next if($Base eq $Type);
4829 my $Num = $Repl->{$Type};
4830 my $Replace = macro_mangle($Num);
4831 $Base=~s/\Q$Type\E/$Replace/;
4832 $Repl->{$Base} = $Repl->{$Value};
4833 }
4834}
4835
4836sub macro_mangle($)
4837{
4838 my $Num = $_[0];
4839 if($Num==-1) {
4840 return "S_";
4841 }
4842 else
4843 {
4844 my $Code = "";
4845 if($Num<10)
4846 { # S0_, S1_, S2_, ...
4847 $Code = $Num;
4848 }
4849 elsif($Num>=10 and $Num<=35)
4850 { # SA_, SB_, SC_, ...
4851 $Code = chr(55+$Num);
4852 }
4853 else
4854 { # S10_, S11_, S12_
4855 $Code = $Num-26; # 26 is length of english alphabet
4856 }
4857 return "S".$Code."_";
4858 }
4859}
4860
4861sub write_stdcxx_substitution($)
4862{
4863 my $Mangled = $_[0];
4864 if($StdcxxMangling{$Mangled}) {
4865 return $StdcxxMangling{$Mangled};
4866 }
4867 else
4868 {
4869 my @Repls = keys(%StdcxxMangling);
4870 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4871 foreach my $MangledType (@Repls)
4872 {
4873 my $Replace = $StdcxxMangling{$MangledType};
4874 #if($Mangled!~/$Replace/) {
4875 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4876 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4877 #}
4878 }
4879 }
4880 return $Mangled;
4881}
4882
4883sub write_substitution($$)
4884{
4885 my ($Mangled, $Repl) = @_;
4886 if(defined $Repl->{$Mangled}
4887 and my $MnglNum = $Repl->{$Mangled}) {
4888 $Mangled = macro_mangle($MnglNum);
4889 }
4890 else
4891 {
4892 my @Repls = keys(%{$Repl});
4893 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4894 # FIXME: how to apply replacements? by num or by pos
4895 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4896 foreach my $MangledType (@Repls)
4897 {
4898 my $Replace = macro_mangle($Repl->{$MangledType});
4899 if($Mangled!~/$Replace/) {
4900 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4901 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4902 }
4903 }
4904 }
4905 return $Mangled;
4906}
4907
4908sub delete_keywords($)
4909{
4910 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004911 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004912 return $TypeName;
4913}
4914
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004915sub uncover_typedefs($$)
4916{
4917 my ($TypeName, $LibVersion) = @_;
4918 return "" if(not $TypeName);
4919 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4920 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4921 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004922 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004923 while($TypeName_New ne $TypeName_Pre)
4924 {
4925 $TypeName_Pre = $TypeName_New;
4926 my $TypeName_Copy = $TypeName_New;
4927 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004928 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004929 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004930 if(not $Intrinsic_Keywords{$1}) {
4931 $Words{$1} = 1;
4932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004933 }
4934 foreach my $Word (keys(%Words))
4935 {
4936 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4937 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004938 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004939 if($BaseType_Name=~/\([\*]+\)/)
4940 { # FuncPtr
4941 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4942 {
4943 my $Type_Suffix = $1;
4944 $TypeName_New = $BaseType_Name;
4945 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004946 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004947 }
4948 }
4949 }
4950 else
4951 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004952 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004953 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004954 }
4955 }
4956 }
4957 }
4958 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4959}
4960
4961sub isInternal($)
4962{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004963 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4964 {
4965 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4966 {
4967 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4968 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4969 return 1;
4970 }
4971 }
4972 }
4973 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004974}
4975
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004976sub getDataVal($$)
4977{
4978 my ($InfoId, $TypeId) = @_;
4979 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4980 {
4981 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4982 {
4983 if(defined $LibInfo{$Version}{"info_type"}{$1}
4984 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004985 {
4986 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004987 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004988 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4989 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004990 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004991 if(my $Addr = getTreeAttr_Op($1)) {
4992 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004993 }
4994 }
4995 }
4996 }
4997 else {
4998 return getInitVal($1, $TypeId);
4999 }
5000 }
5001 }
5002 return undef;
5003}
5004
5005sub getInitVal($$)
5006{
5007 my ($InfoId, $TypeId) = @_;
5008 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
5009 {
5010 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
5011 {
5012 if($InfoType eq "integer_cst")
5013 {
5014 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005015 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005016 { # characters
5017 $Val = chr($Val);
5018 }
5019 return $Val;
5020 }
5021 elsif($InfoType eq "string_cst") {
5022 return getNodeStrCst($InfoId);
5023 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005024 elsif($InfoType eq "var_decl")
5025 {
5026 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
5027 return $Name;
5028 }
5029 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005030 }
5031 }
5032 return undef;
5033}
5034
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005035sub set_Class_And_Namespace($)
5036{
5037 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005038 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005039 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005040 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005041 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005042 my $NSInfoId = $1;
5043 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
5044 {
5045 if($InfoType eq "namespace_decl") {
5046 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
5047 }
5048 elsif($InfoType eq "record_type") {
5049 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
5050 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005051 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005052 }
5053 }
5054 if($SymbolInfo{$Version}{$InfoId}{"Class"}
5055 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005056 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005057 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005058 { # skip
5059 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005060 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005061 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005062
5063 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005064}
5065
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005066sub debugMangling($)
5067{
5068 my $LibVersion = $_[0];
5069 my %Mangled = ();
5070 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
5071 {
5072 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
5073 {
5074 if($Mngl=~/\A(_Z|\?)/) {
5075 $Mangled{$Mngl}=$InfoId;
5076 }
5077 }
5078 }
5079 translateSymbols(keys(%Mangled), $LibVersion);
5080 foreach my $Mngl (keys(%Mangled))
5081 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005082 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
5083 my $U2 = $tr_name{$Mngl};
5084 if($U1 ne $U2) {
5085 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005086 }
5087 }
5088}
5089
5090sub linkSymbol($)
5091{ # link symbols from shared libraries
5092 # with the symbols from header files
5093 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005094 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005095 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005096 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5097 or $EMERGENCY_MODE_48)
5098 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
5099 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
5100 # GCC 4.8 doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005101 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005102 {
5103 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
5104 return correct_incharge($InfoId, $Version, $Mangled);
5105 }
5106 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005107 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005108 or not $BinaryOnly
5109 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005110 { # 1. --headers-only mode
5111 # 2. not mangled src-only symbols
5112 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
5113 return $Mangled;
5114 }
5115 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005116 }
5117 return "";
5118}
5119
5120sub setLanguage($$)
5121{
5122 my ($LibVersion, $Lang) = @_;
5123 if(not $UserLang) {
5124 $COMMON_LANGUAGE{$LibVersion} = $Lang;
5125 }
5126}
5127
5128sub getSymbolInfo($)
5129{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005130 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005131 if(isInternal($InfoId)) {
5132 return;
5133 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005134 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5135 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005136 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5137 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005138 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005139 return;
5140 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005141 setFuncAccess($InfoId);
5142 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005143 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5144 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005145 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005146 return;
5147 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005148
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005149 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005150 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005151 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005152 if(not defined $TypeInfo{$Version}{$Return}
5153 or not $TypeInfo{$Version}{$Return}{"Name"})
5154 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005155 delete($SymbolInfo{$Version}{$InfoId});
5156 return;
5157 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005158 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005159 }
5160 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5161 {
5162 if(defined $MissedTypedef{$Version}{$Rid})
5163 {
5164 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5165 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5166 }
5167 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005168 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005169 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5170 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005171 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005172 my $Orig = getFuncOrig($InfoId);
5173 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005174 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5175 {
5176 delete($SymbolInfo{$Version}{$InfoId});
5177 return;
5178 }
5179
5180 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005181 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005182 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005183 return;
5184 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005185
5186 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005187 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005188 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5189
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005190 my @TParams = getTParams($Orig, "Func");
5191 if(not @TParams)
5192 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005193 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005194 return;
5195 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005196 foreach my $Pos (0 .. $#TParams)
5197 {
5198 my $Val = $TParams[$Pos];
5199 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5200
5201 if($Tmpl)
5202 {
5203 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5204 {
5205 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5206 }
5207 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005208 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005209
5210 if($Tmpl)
5211 {
5212 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5213 {
5214 if($Pos>$#TParams)
5215 {
5216 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5217 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5218 }
5219 }
5220 }
5221
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005222 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5223 { # operator<< <T>, operator>> <T>
5224 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5225 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005226 if(@TParams) {
5227 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5228 }
5229 else {
5230 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5231 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005232 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005233 }
5234 else
5235 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005236 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005237 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005238 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5239 {
5240 if($OSgroup eq "windows")
5241 { # cut the offset
5242 $MnglName=~s/\@\d+\Z//g;
5243 }
5244 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5245
5246 # NOTE: mangling of some symbols may change depending on GCC version
5247 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5248 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5249 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005250
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005251 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005252 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005253 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005254 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005255 return;
5256 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005257 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005258 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005259 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005260 if($Skip)
5261 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005262 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005263 return;
5264 }
5265 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005266 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5267 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5268 }
5269
5270 if(set_Class_And_Namespace($InfoId))
5271 {
5272 delete($SymbolInfo{$Version}{$InfoId});
5273 return;
5274 }
5275
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005276 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5277 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005278 if(not defined $TypeInfo{$Version}{$ClassId}
5279 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5280 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005281 delete($SymbolInfo{$Version}{$InfoId});
5282 return;
5283 }
5284 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005285 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5286 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005287 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005288 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005289 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005290 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005291 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005292 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005293 }
5294 if($COMMON_LANGUAGE{$Version} eq "C++")
5295 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005296 # C++ or --headers-only mode
5297 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005298 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005299 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5300 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005301 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005302 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005303 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005304 if(my $Mangled = linkSymbol($InfoId)) {
5305 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005306 }
5307 }
5308 if($OStarget eq "windows")
5309 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005310 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005311 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005312 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005313 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005314 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005315 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005316 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005317 }
5318 }
5319 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005320 else
5321 { # not mangled in C
5322 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5323 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005324 if(not $CheckHeadersOnly
5325 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5326 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5327 {
5328 my $Incorrect = 0;
5329
5330 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5331 {
5332 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5333 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5334 { # mangled in the TU dump, but not mangled in the library
5335 $Incorrect = 1;
5336 }
5337 }
5338 else
5339 {
5340 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5341 { # all C++ functions are not mangled in the TU dump
5342 $Incorrect = 1;
5343 }
5344 }
5345 if($Incorrect)
5346 {
5347 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5348 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5349 }
5350 }
5351 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005352 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005353 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005354 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005355 return;
5356 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005357 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005358 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005359 { # identify virtual and pure virtual functions
5360 # NOTE: constructors cannot be virtual
5361 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5362 # in the TU dump, so taking it from the original symbol
5363 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5364 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5365 { # NOTE: D2 destructors are not present in a v-table
5366 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5367 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005368 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005369 if(isInline($InfoId)) {
5370 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005371 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005372 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005373 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5374 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005375 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5376 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005377 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005378 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005379 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005380 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005381 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005382 }
5383 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005384 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5385 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005386 if(not $ExtraDump)
5387 {
5388 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5389 { # non-target symbols
5390 delete($SymbolInfo{$Version}{$InfoId});
5391 return;
5392 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005393 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005394 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005395 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5396 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5397 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5398 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005399 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005400 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5401 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005402 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005403 return;
5404 }
5405 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005406 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005407 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005408 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005409 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005410 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005411 return;
5412 }
5413 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005414 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005415 }
5416 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005417 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5418 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5419 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005420 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005421 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5422 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005423 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005424 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005425 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005426 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005427 }
5428 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005429 if(getFuncLink($InfoId) eq "Static") {
5430 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005431 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005432 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5433 {
5434 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5435 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005436 if($Unmangled=~/\.\_\d/)
5437 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005438 delete($SymbolInfo{$Version}{$InfoId});
5439 return;
5440 }
5441 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005442 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005443
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005444 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5445 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005446 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005447 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5448 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005449 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005450
5451 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5452 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5453 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005454
5455 if($ExtraDump) {
5456 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5457 }
5458}
5459
5460sub guessHeader($)
5461{
5462 my $InfoId = $_[0];
5463 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5464 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5465 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5466 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5467 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5468 {
5469 if(get_filename($HPath) eq $Header)
5470 {
5471 my $HDir = get_filename(get_dirname($HPath));
5472 if($HDir ne "include"
5473 and $HDir=~/\A[a-z]+\Z/i) {
5474 return join_P($HDir, $Header);
5475 }
5476 }
5477 }
5478 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005479}
5480
5481sub isInline($)
5482{ # "body: undefined" in the tree
5483 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005484 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5485 {
5486 if($Info=~/ undefined /i) {
5487 return 0;
5488 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005489 }
5490 return 1;
5491}
5492
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005493sub hasThrow($)
5494{
5495 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5496 {
5497 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5498 return getTreeAttr_Unql($1, "unql");
5499 }
5500 }
5501 return 1;
5502}
5503
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005504sub getTypeId($)
5505{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005506 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5507 {
5508 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5509 return $1;
5510 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005511 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005512 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005513}
5514
5515sub setTypeMemb($$)
5516{
5517 my ($TypeId, $TypeAttr) = @_;
5518 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005519 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005520 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005521 if($TypeType eq "Enum")
5522 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005523 my $MInfoId = getTreeAttr_Csts($TypeId);
5524 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005525 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005526 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5527 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005528 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005529 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5530 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005531 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005532 }
5533 }
5534 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5535 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005536 my $MInfoId = getTreeAttr_Flds($TypeId);
5537 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005538 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005539 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5540 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005541 if(not $IType or $IType ne "field_decl")
5542 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005543
5544 if($IType eq "var_decl")
5545 { # static field
5546 $StaticFields = 1;
5547 }
5548
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005549 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005550 next;
5551 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005552 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005553 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005554 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005555 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005556 }
5557 if(not $StructMembName)
5558 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005559 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005560 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005561 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005562 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5563 if(isAnon($UnnamedTName))
5564 { # rename unnamed fields to unnamed0, unnamed1, ...
5565 $StructMembName = "unnamed".($UnnamedPos++);
5566 }
5567 }
5568 }
5569 if(not $StructMembName)
5570 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005571 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005572 next;
5573 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005574 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005575 if(defined $MissedTypedef{$Version}{$MembTypeId})
5576 {
5577 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5578 $MembTypeId = $AddedTid;
5579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005580 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005581
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005582 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5583 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005584 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005585 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005586 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5587 }
5588 if($MInfo=~/spec:\s*mutable /)
5589 { # mutable fields
5590 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005591 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005592 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005593 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5594 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005595 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005596 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005597 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005598 }
5599 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005600 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005601 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5602 { # template
5603 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5604 }
5605 else {
5606 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5607 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005608 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005609
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005610 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005611 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005612 }
5613 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005614
5615 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005616}
5617
5618sub setFuncParams($)
5619{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005620 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005621 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005622
5623 my $FType = getFuncType($InfoId);
5624
5625 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005626 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005627 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5628 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005629 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005630 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005631 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5632 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005633 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005634 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5635 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005636 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005637 else
5638 { # skip
5639 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005640 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005641 # skip "this"-parameter
5642 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005643 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005644 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005645 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005646 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005647 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5648 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5649 if(not $ParamName)
5650 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005651 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005652 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005653 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5654 {
5655 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5656 $ParamTypeId = $AddedTid;
5657 }
5658 }
5659 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005660 if(not $PType or $PType eq "Unknown") {
5661 return 1;
5662 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005663 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005664 if(not $PTName) {
5665 return 1;
5666 }
5667 if($PTName eq "void") {
5668 last;
5669 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005670 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005671 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005672 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005673 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005674 $ParamInfoId = getNextElem($ParamInfoId);
5675 next;
5676 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005677 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005678
5679 if(my %Base = get_BaseType($ParamTypeId, $Version))
5680 {
5681 if(defined $Base{"Template"}) {
5682 return 1;
5683 }
5684 }
5685
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005686 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005687 if(my $Algn = getAlgn($ParamInfoId)) {
5688 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5689 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005690 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5691 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005692 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005693 }
5694 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005695 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005696 if($ParamName ne "this" or $FType ne "Method") {
5697 $PPos += 1;
5698 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005699 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005700 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005701 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005702 }
5703 return 0;
5704}
5705
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005706sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005707{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005708 my ($InfoId, $Vtt_Pos) = @_;
5709 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005710 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005711 my $FType = getFuncType($InfoId);
5712
5713 if($FType eq "Method")
5714 {
5715 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005716 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005717 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005718 if(not $ParamListElemId)
5719 { # foo(...)
5720 return 1;
5721 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005722 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005723 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005724 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005725 { # actual params: may differ from formal args
5726 # formal int*const
5727 # actual: int*
5728 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005729 {
5730 $Vtt_Pos=-1;
5731 $ParamListElemId = getNextElem($ParamListElemId);
5732 next;
5733 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005734 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5735 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005736 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005737 $HaveVoid = 1;
5738 last;
5739 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005740 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005741 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005742 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5743 {
5744 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5745 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5746 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005747 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005748 }
5749 }
5750 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5751 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005752 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005753 { # params
5754 if($OldId ne $ParamTypeId)
5755 {
5756 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5757 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5758
5759 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5760 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5761 }
5762 }
5763 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005764 }
5765 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005766 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005767 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005768 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5769 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005770 if($PurpType eq "nop_expr")
5771 { # func ( const char* arg = (const char*)(void*)0 )
5772 $PurpId = getTreeAttr_Op($PurpId);
5773 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005774 my $Val = getInitVal($PurpId, $ParamTypeId);
5775 if(defined $Val) {
5776 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005778 }
5779 }
5780 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005781 if($Pos!=0 or $FType ne "Method") {
5782 $PPos += 1;
5783 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005784 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005785 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005786 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005787}
5788
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005789sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005790{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005791 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5792 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005793 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5794 return $1;
5795 }
5796 }
5797 return "";
5798}
5799
5800sub getTreeAttr_Chain($)
5801{
5802 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5803 {
5804 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5805 return $1;
5806 }
5807 }
5808 return "";
5809}
5810
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005811sub getTreeAttr_Unql($)
5812{
5813 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5814 {
5815 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5816 return $1;
5817 }
5818 }
5819 return "";
5820}
5821
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005822sub getTreeAttr_Scpe($)
5823{
5824 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5825 {
5826 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5827 return $1;
5828 }
5829 }
5830 return "";
5831}
5832
5833sub getTreeAttr_Type($)
5834{
5835 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5836 {
5837 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5838 return $1;
5839 }
5840 }
5841 return "";
5842}
5843
5844sub getTreeAttr_Name($)
5845{
5846 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5847 {
5848 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5849 return $1;
5850 }
5851 }
5852 return "";
5853}
5854
5855sub getTreeAttr_Mngl($)
5856{
5857 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5858 {
5859 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5860 return $1;
5861 }
5862 }
5863 return "";
5864}
5865
5866sub getTreeAttr_Prms($)
5867{
5868 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5869 {
5870 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5871 return $1;
5872 }
5873 }
5874 return "";
5875}
5876
5877sub getTreeAttr_Fncs($)
5878{
5879 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5880 {
5881 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5882 return $1;
5883 }
5884 }
5885 return "";
5886}
5887
5888sub getTreeAttr_Csts($)
5889{
5890 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5891 {
5892 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5893 return $1;
5894 }
5895 }
5896 return "";
5897}
5898
5899sub getTreeAttr_Purp($)
5900{
5901 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5902 {
5903 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5904 return $1;
5905 }
5906 }
5907 return "";
5908}
5909
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005910sub getTreeAttr_Op($)
5911{
5912 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5913 {
5914 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5915 return $1;
5916 }
5917 }
5918 return "";
5919}
5920
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005921sub getTreeAttr_Valu($)
5922{
5923 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5924 {
5925 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5926 return $1;
5927 }
5928 }
5929 return "";
5930}
5931
5932sub getTreeAttr_Flds($)
5933{
5934 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5935 {
5936 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5937 return $1;
5938 }
5939 }
5940 return "";
5941}
5942
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005943sub getTreeAttr_Binf($)
5944{
5945 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5946 {
5947 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5948 return $1;
5949 }
5950 }
5951 return "";
5952}
5953
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005954sub getTreeAttr_Args($)
5955{
5956 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5957 {
5958 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005959 return $1;
5960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005961 }
5962 return "";
5963}
5964
5965sub getTreeValue($)
5966{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005967 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5968 {
5969 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5970 return $1;
5971 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005972 }
5973 return "";
5974}
5975
5976sub getTreeAccess($)
5977{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005978 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005979 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005980 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5981 {
5982 my $Access = $1;
5983 if($Access eq "prot") {
5984 return "protected";
5985 }
5986 elsif($Access eq "priv") {
5987 return "private";
5988 }
5989 }
5990 elsif($Info=~/ protected /)
5991 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005992 return "protected";
5993 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005994 elsif($Info=~/ private /)
5995 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005996 return "private";
5997 }
5998 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005999 return "public";
6000}
6001
6002sub setFuncAccess($)
6003{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006004 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006005 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006006 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006007 }
6008 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006009 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006010 }
6011}
6012
6013sub setTypeAccess($$)
6014{
6015 my ($TypeId, $TypeAttr) = @_;
6016 my $Access = getTreeAccess($TypeId);
6017 if($Access eq "protected") {
6018 $TypeAttr->{"Protected"} = 1;
6019 }
6020 elsif($Access eq "private") {
6021 $TypeAttr->{"Private"} = 1;
6022 }
6023}
6024
6025sub setFuncKind($)
6026{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006027 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6028 {
6029 if($Info=~/pseudo tmpl/) {
6030 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
6031 }
6032 elsif($Info=~/ constructor /) {
6033 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
6034 }
6035 elsif($Info=~/ destructor /) {
6036 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
6037 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006038 }
6039}
6040
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006041sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006042{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006043 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6044 {
6045 if($Info=~/spec[ ]*:[ ]*pure /) {
6046 return "PureVirt";
6047 }
6048 elsif($Info=~/spec[ ]*:[ ]*virt /) {
6049 return "Virt";
6050 }
6051 elsif($Info=~/ pure\s+virtual /)
6052 { # support for old GCC versions
6053 return "PureVirt";
6054 }
6055 elsif($Info=~/ virtual /)
6056 { # support for old GCC versions
6057 return "Virt";
6058 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006059 }
6060 return "";
6061}
6062
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006063sub getFuncLink($)
6064{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006065 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6066 {
6067 if($Info=~/link[ ]*:[ ]*static /) {
6068 return "Static";
6069 }
6070 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006071 return $1;
6072 }
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 Ponomarenko74b33ee2012-12-14 15:24:09 +04006077sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006078{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006079 my ($Symbol, $LibVersion) = @_;
6080 return "" if(not $Symbol or not $LibVersion);
6081 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
6082 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006083 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006084 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
6085 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
6086 }
6087 }
6088 if($NS)
6089 {
6090 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6091 return $NS;
6092 }
6093 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006094 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006095 while($NS=~s/::[^:]+\Z//)
6096 {
6097 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6098 return $NS;
6099 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006100 }
6101 }
6102 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006103
6104 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006105}
6106
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006107sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006108{
6109 my ($TypeName, $LibVersion) = @_;
6110 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006111 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006112 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006113 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6114 return $NS;
6115 }
6116 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006117 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006118 while($NS=~s/::[^:]+\Z//)
6119 {
6120 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6121 return $NS;
6122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006123 }
6124 }
6125 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006126 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006127}
6128
6129sub getNameSpace($)
6130{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006131 my $InfoId = $_[0];
6132 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006133 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006134 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006135 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006136 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006137 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006138 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6139 {
6140 my $NameSpace = getTreeStr($1);
6141 if($NameSpace eq "::")
6142 { # global namespace
6143 return "";
6144 }
6145 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6146 $NameSpace = $BaseNameSpace."::".$NameSpace;
6147 }
6148 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6149 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006150 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006151 else {
6152 return "";
6153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006154 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006155 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006156 { # inside data type
6157 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6158 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006159 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006160 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006161 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006162 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006163}
6164
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006165sub getEnumMembVal($)
6166{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006167 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006168 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006169 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6170 {
6171 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6172 {
6173 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6174 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6175 return getTreeValue($1);
6176 }
6177 else
6178 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6179 return getTreeValue($1);
6180 }
6181 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006182 }
6183 }
6184 return "";
6185}
6186
6187sub getSize($)
6188{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006189 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6190 {
6191 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6192 return getTreeValue($1);
6193 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006194 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006195 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006196}
6197
6198sub getAlgn($)
6199{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006200 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6201 {
6202 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6203 return $1;
6204 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006205 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006206 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006207}
6208
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006209sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006210{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006211 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6212 {
6213 if($Info=~/ bitfield /) {
6214 return getSize($_[0]);
6215 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006216 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006217 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006218}
6219
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006220sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006221{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006222 if(my $Chan = getTreeAttr_Chan($_[0])) {
6223 return $Chan;
6224 }
6225 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6226 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006227 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006228 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006229}
6230
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006231sub registerHeader($$)
6232{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006233 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006234 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006235 return "";
6236 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006237 if(is_abs($Header) and not -f $Header)
6238 { # incorrect absolute path
6239 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006240 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006241 if(skipHeader($Header, $LibVersion))
6242 { # skip
6243 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006244 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006245 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6246 {
6247 detect_header_includes($Header_Path, $LibVersion);
6248
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006249 if(defined $Tolerance and $Tolerance=~/3/)
6250 { # 3 - skip headers that include non-Linux headers
6251 if($OSgroup ne "windows")
6252 {
6253 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6254 {
6255 if(specificHeader($Inc, "windows")) {
6256 return "";
6257 }
6258 }
6259 }
6260 }
6261
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006262 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6263 { # redirect
6264 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6265 or skipHeader($RHeader_Path, $LibVersion))
6266 { # skip
6267 return "";
6268 }
6269 $Header_Path = $RHeader_Path;
6270 }
6271 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6272 { # skip
6273 return "";
6274 }
6275
6276 if(my $HName = get_filename($Header_Path))
6277 { # register
6278 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6279 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6280 }
6281
6282 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6283 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006284 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006285 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006286 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006287 }
6288
6289 if($CheckHeadersOnly
6290 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6291 { # /usr/include/c++/4.6.1/...
6292 $STDCXX_TESTING = 1;
6293 }
6294
6295 return $Header_Path;
6296 }
6297 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006298}
6299
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006300sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006301{
6302 my ($Dir, $WithDeps, $LibVersion) = @_;
6303 $Dir=~s/[\/\\]+\Z//g;
6304 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006305 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006306
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006307 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006308 if($WithDeps)
6309 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006310 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6311 return;
6312 }
6313 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6314 $Mode = "DepsOnly";
6315 }
6316 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006317 else
6318 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006319 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6320 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6321 return;
6322 }
6323 }
6324 $Header_Dependency{$LibVersion}{$Dir} = 1;
6325 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6326 if($Mode eq "DepsOnly")
6327 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006328 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006329 $Header_Dependency{$LibVersion}{$Path} = 1;
6330 }
6331 return;
6332 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006333 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006334 {
6335 if($WithDeps)
6336 {
6337 my $SubDir = $Path;
6338 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6339 { # register all sub directories
6340 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6341 }
6342 }
6343 next if(is_not_header($Path));
6344 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006345 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006346 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006347 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6348 }
6349 }
6350 if(get_filename($Dir) eq "include")
6351 { # search for "lib/include/" directory
6352 my $LibDir = $Dir;
6353 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006354 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006355 }
6356 }
6357}
6358
6359sub parse_redirect($$$)
6360{
6361 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006362 my @Errors = ();
6363 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6364 push(@Errors, $1);
6365 }
6366 my $Redirect = "";
6367 foreach (@Errors)
6368 {
6369 s/\s{2,}/ /g;
6370 if(/(only|must\ include
6371 |update\ to\ include
6372 |replaced\ with
6373 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006374 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006375 {
6376 $Redirect = $2;
6377 last;
6378 }
6379 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6380 {
6381 $Redirect = $2;
6382 last;
6383 }
6384 elsif(/this\ header\ should\ not\ be\ used
6385 |programs\ should\ not\ directly\ include
6386 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6387 |is\ not\ supported\ API\ for\ general\ use
6388 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006389 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006390 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6391 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6392 }
6393 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006394 if($Redirect)
6395 {
6396 $Redirect=~s/\A<//g;
6397 $Redirect=~s/>\Z//g;
6398 }
6399 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006400}
6401
6402sub parse_includes($$)
6403{
6404 my ($Content, $Path) = @_;
6405 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006406 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006407 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006408 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006409 my $Method = substr($Header, 0, 1, "");
6410 substr($Header, length($Header)-1, 1, "");
6411 $Header = path_format($Header, $OSgroup);
6412 if($Method eq "\"" or is_abs($Header))
6413 {
6414 if(-e join_P(get_dirname($Path), $Header))
6415 { # relative path exists
6416 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006417 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006418 else
6419 { # include "..." that doesn't exist is equal to include <...>
6420 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006421 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006422 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006423 else {
6424 $Includes{$Header} = 1;
6425 }
6426 }
6427 if($ExtraInfo)
6428 {
6429 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6430 { # FT_FREETYPE_H
6431 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006432 }
6433 }
6434 return \%Includes;
6435}
6436
6437sub ignore_path($)
6438{
6439 my $Path = $_[0];
6440 if($Path=~/\~\Z/)
6441 {# skipping system backup files
6442 return 1;
6443 }
6444 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6445 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6446 return 1;
6447 }
6448 return 0;
6449}
6450
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006451sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006452{
6453 my ($ArrRef, $W) = @_;
6454 return if(length($W)<2);
6455 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6456}
6457
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006458sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006459{
6460 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006461
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006462 $H1=~s/\.[a-z]+\Z//ig;
6463 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006464
6465 my $Hname1 = get_filename($H1);
6466 my $Hname2 = get_filename($H2);
6467 my $HDir1 = get_dirname($H1);
6468 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006469 my $Dirname1 = get_filename($HDir1);
6470 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006471
6472 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6473 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6474
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006475 if($_[0] eq $_[1]
6476 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006477 return 0;
6478 }
6479 elsif($H1=~/\A\Q$H2\E/) {
6480 return 1;
6481 }
6482 elsif($H2=~/\A\Q$H1\E/) {
6483 return -1;
6484 }
6485 elsif($HDir1=~/\Q$Hname1\E/i
6486 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006487 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006488 return -1;
6489 }
6490 elsif($HDir2=~/\Q$Hname2\E/i
6491 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006492 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006493 return 1;
6494 }
6495 elsif($Hname1=~/\Q$Dirname1\E/i
6496 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006497 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006498 return -1;
6499 }
6500 elsif($Hname2=~/\Q$Dirname2\E/i
6501 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006502 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006503 return 1;
6504 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006505 elsif($Hname1=~/(config|lib|util)/i
6506 and $Hname2!~/(config|lib|util)/i)
6507 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006508 return -1;
6509 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006510 elsif($Hname2=~/(config|lib|util)/i
6511 and $Hname1!~/(config|lib|util)/i)
6512 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006513 return 1;
6514 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006515 else
6516 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006517 my $R1 = checkRelevance($H1);
6518 my $R2 = checkRelevance($H2);
6519 if($R1 and not $R2)
6520 { # libebook/e-book.h
6521 return -1;
6522 }
6523 elsif($R2 and not $R1)
6524 { # libebook/e-book.h
6525 return 1;
6526 }
6527 else
6528 {
6529 return (lc($H1) cmp lc($H2));
6530 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006531 }
6532}
6533
6534sub searchForHeaders($)
6535{
6536 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006537
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006538 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006539 registerGccHeaders();
6540
6541 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6542 { # c++ standard include paths
6543 registerCppHeaders();
6544 }
6545
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006546 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006547 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6548 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006549 {
6550 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006551 if($SystemRoot)
6552 {
6553 if(is_abs($Path)) {
6554 $Path = $SystemRoot.$Path;
6555 }
6556 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006557 if(not -e $Path) {
6558 exitStatus("Access_Error", "can't access \'$Path\'");
6559 }
6560 elsif(-f $Path) {
6561 exitStatus("Access_Error", "\'$Path\' - not a directory");
6562 }
6563 elsif(-d $Path)
6564 {
6565 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006566 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006567 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6568 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006569 }
6570 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006571 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006572 }
6573 }
6574 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006575 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006576 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6577 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006578
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006579 # registering directories
6580 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6581 {
6582 next if(not -e $Path);
6583 $Path = get_abs_path($Path);
6584 $Path = path_format($Path, $OSgroup);
6585 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006586 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006587 }
6588 elsif(-f $Path)
6589 {
6590 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006591 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006592 and not $LocalIncludes{$Dir})
6593 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006594 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006595 # if(my $OutDir = get_dirname($Dir))
6596 # { # registering the outer directory
6597 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6598 # and not $LocalIncludes{$OutDir}) {
6599 # registerDir($OutDir, 0, $LibVersion);
6600 # }
6601 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006602 }
6603 }
6604 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006605
6606 # clean memory
6607 %RegisteredDirs = ();
6608
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006609 # registering headers
6610 my $Position = 0;
6611 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6612 {
6613 if(is_abs($Dest) and not -e $Dest) {
6614 exitStatus("Access_Error", "can't access \'$Dest\'");
6615 }
6616 $Dest = path_format($Dest, $OSgroup);
6617 if(is_header($Dest, 1, $LibVersion))
6618 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006619 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006620 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6621 }
6622 }
6623 elsif(-d $Dest)
6624 {
6625 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006626 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006627 {
6628 next if(ignore_path($Path));
6629 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006630 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006631 push(@Registered, $HPath);
6632 }
6633 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006634 @Registered = sort {sortHeaders($a, $b)} @Registered;
6635 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006636 foreach my $Path (@Registered) {
6637 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6638 }
6639 }
6640 else {
6641 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6642 }
6643 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006644
6645 if(defined $Tolerance and $Tolerance=~/4/)
6646 { # 4 - skip headers included by others
6647 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6648 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006649 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006650 delete($Registered_Headers{$LibVersion}{$Path});
6651 }
6652 }
6653 }
6654
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006655 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6656 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006657 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006658 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006659 if(is_abs($Header) and not -f $Header) {
6660 exitStatus("Access_Error", "can't access file \'$Header\'");
6661 }
6662 $Header = path_format($Header, $OSgroup);
6663 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6664 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006665 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006666 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006667 }
6668 else {
6669 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6670 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006671 }
6672 }
6673 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6674 { # set relative paths (for duplicates)
6675 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6676 { # search for duplicates
6677 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6678 my $Prefix = get_dirname($FirstPath);
6679 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6680 { # detect a shortest distinguishing prefix
6681 my $NewPrefix = $1;
6682 my %Identity = ();
6683 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6684 {
6685 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6686 $Identity{$Path} = $1;
6687 }
6688 }
6689 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6690 { # all names are differend with current prefix
6691 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6692 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6693 }
6694 last;
6695 }
6696 $Prefix = $NewPrefix; # increase prefix
6697 }
6698 }
6699 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006700
6701 # clean memory
6702 %HeaderName_Paths = ();
6703
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006704 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6705 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006706 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006707 my ($Pos, $PairPos) = (-1, -1);
6708 my ($Path, $PairPath) = ();
6709 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6710 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6711 foreach my $Header_Path (@Paths)
6712 {
6713 if(get_filename($Header_Path) eq $PairName)
6714 {
6715 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6716 $PairPath = $Header_Path;
6717 }
6718 if(get_filename($Header_Path) eq $HeaderName)
6719 {
6720 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6721 $Path = $Header_Path;
6722 }
6723 }
6724 if($PairPos!=-1 and $Pos!=-1
6725 and int($PairPos)<int($Pos))
6726 {
6727 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6728 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6729 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6730 }
6731 }
6732 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6733 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6734 }
6735}
6736
6737sub detect_real_includes($$)
6738{
6739 my ($AbsPath, $LibVersion) = @_;
6740 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6741 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6742 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6743 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6744 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006745 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6746
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006747 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6748 return () if(not $Path);
6749 open(PREPROC, $Path);
6750 while(<PREPROC>)
6751 {
6752 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6753 {
6754 my $Include = path_format($1, $OSgroup);
6755 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6756 next;
6757 }
6758 if($Include eq $AbsPath) {
6759 next;
6760 }
6761 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6762 }
6763 }
6764 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006765 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6766}
6767
6768sub detect_header_includes($$)
6769{
6770 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006771 return if(not $LibVersion or not $Path);
6772 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6773 return;
6774 }
6775 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6776
6777 if(not -e $Path) {
6778 return;
6779 }
6780
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006781 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006782 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6783 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006784 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006785 {
6786 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006787 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006788 }
6789 if($RedirectPath ne $Path) {
6790 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6791 }
6792 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006793 else
6794 { # can't find
6795 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6796 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006797 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006798 if(my $Inc = parse_includes($Content, $Path))
6799 {
6800 foreach my $Include (keys(%{$Inc}))
6801 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006802 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006803
6804 if(defined $Tolerance and $Tolerance=~/4/)
6805 {
6806 if(my $HPath = identifyHeader($Include, $LibVersion))
6807 {
6808 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6809 }
6810 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006811 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006813}
6814
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006815sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006816{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006817 my $Path = $_[0];
6818 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006819 if($OStarget eq "symbian")
6820 {
6821 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6822 { # epoc32/include/libc/{stdio, ...}.h
6823 return 1;
6824 }
6825 }
6826 else
6827 {
6828 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6829 { # /usr/include/{stdio, ...}.h
6830 return 1;
6831 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006832 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006833 return 0;
6834}
6835
6836sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006837{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006838 my $Dir = $_[0];
6839 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006840 if($OStarget eq "symbian")
6841 {
6842 if(get_filename($OutDir) eq "libc"
6843 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6844 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6845 return 1;
6846 }
6847 }
6848 else
6849 { # linux
6850 if($OutDir eq "/usr/include"
6851 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6852 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6853 return 1;
6854 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006855 }
6856 return 0;
6857}
6858
6859sub detect_recursive_includes($$)
6860{
6861 my ($AbsPath, $LibVersion) = @_;
6862 return () if(not $AbsPath);
6863 if(isCyclical(\@RecurInclude, $AbsPath)) {
6864 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6865 }
6866 my ($AbsDir, $Name) = separate_path($AbsPath);
6867 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006868 { # system GLIBC internals
6869 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006870 }
6871 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6872 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6873 }
6874 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006875
6876 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6877 { # skip /usr/include/c++/*/ headers
6878 return () if(not $ExtraInfo);
6879 }
6880
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006881 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006882 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006883 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006884 { # check "real" (non-"model") include paths
6885 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6886 pop(@RecurInclude);
6887 return @Paths;
6888 }
6889 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6890 detect_header_includes($AbsPath, $LibVersion);
6891 }
6892 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6893 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006894 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006895 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006896 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006897 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006898 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006899 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006900 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006901 }
6902 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006903 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006904 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006905 { # search for the nearest header
6906 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006907 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006908 if(-f $Candidate) {
6909 $HPath = $Candidate;
6910 }
6911 }
6912 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006913 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006914 }
6915 next if(not $HPath);
6916 if($HPath eq $AbsPath) {
6917 next;
6918 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006919
6920 if($Debug)
6921 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006922# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6923# {
6924# print STDERR "$AbsPath -> $HPath\n";
6925# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006926 }
6927
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006928 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6929 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006930 { # only include <...>, skip include "..." prefixes
6931 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6932 }
6933 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6934 {
6935 if($IncPath eq $AbsPath) {
6936 next;
6937 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006938 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6939 if($RIncType==-1)
6940 { # include "..."
6941 $RIncType = $IncType;
6942 }
6943 elsif($RIncType==2)
6944 {
6945 if($IncType!=-1) {
6946 $RIncType = $IncType;
6947 }
6948 }
6949 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006950 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6951 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6952 }
6953 }
6954 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6955 {
6956 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6957 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6958 { # distinguish math.h from glibc and math.h from the tested library
6959 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6960 last;
6961 }
6962 }
6963 }
6964 pop(@RecurInclude);
6965 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6966}
6967
6968sub find_in_framework($$$)
6969{
6970 my ($Header, $Framework, $LibVersion) = @_;
6971 return "" if(not $Header or not $Framework or not $LibVersion);
6972 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6973 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6974 }
6975 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6976 {
6977 if(get_filename($Dependency) eq $Framework
6978 and -f get_dirname($Dependency)."/".$Header) {
6979 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6980 }
6981 }
6982 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6983}
6984
6985sub find_in_defaults($)
6986{
6987 my $Header = $_[0];
6988 return "" if(not $Header);
6989 if(defined $Cache{"find_in_defaults"}{$Header}) {
6990 return $Cache{"find_in_defaults"}{$Header};
6991 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006992 foreach my $Dir (@DefaultIncPaths,
6993 @DefaultGccPaths,
6994 @DefaultCppPaths,
6995 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006996 {
6997 next if(not $Dir);
6998 if(-f $Dir."/".$Header) {
6999 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
7000 }
7001 }
7002 return ($Cache{"find_in_defaults"}{$Header}="");
7003}
7004
7005sub cmp_paths($$)
7006{
7007 my ($Path1, $Path2) = @_;
7008 my @Parts1 = split(/[\/\\]/, $Path1);
7009 my @Parts2 = split(/[\/\\]/, $Path2);
7010 foreach my $Num (0 .. $#Parts1)
7011 {
7012 my $Part1 = $Parts1[$Num];
7013 my $Part2 = $Parts2[$Num];
7014 if($GlibcDir{$Part1}
7015 and not $GlibcDir{$Part2}) {
7016 return 1;
7017 }
7018 elsif($GlibcDir{$Part2}
7019 and not $GlibcDir{$Part1}) {
7020 return -1;
7021 }
7022 elsif($Part1=~/glib/
7023 and $Part2!~/glib/) {
7024 return 1;
7025 }
7026 elsif($Part1!~/glib/
7027 and $Part2=~/glib/) {
7028 return -1;
7029 }
7030 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
7031 return $CmpRes;
7032 }
7033 }
7034 return 0;
7035}
7036
7037sub checkRelevance($)
7038{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007039 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007040 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007041
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007042 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007043 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007044 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007045
7046 my $Name = lc(get_filename($Path));
7047 my $Dir = lc(get_dirname($Path));
7048
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007049 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007050
7051 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007052 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007053 my $Len = length($Token);
7054 next if($Len<=1);
7055 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
7056 { # include/evolution-data-server-1.4/libebook/e-book.h
7057 return 1;
7058 }
7059 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007060 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007061 return 1;
7062 }
7063 }
7064 return 0;
7065}
7066
7067sub checkFamily(@)
7068{
7069 my @Paths = @_;
7070 return 1 if($#Paths<=0);
7071 my %Prefix = ();
7072 foreach my $Path (@Paths)
7073 {
7074 if($SystemRoot) {
7075 $Path = cut_path_prefix($Path, $SystemRoot);
7076 }
7077 if(my $Dir = get_dirname($Path))
7078 {
7079 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
7080 $Prefix{$Dir} += 1;
7081 $Prefix{get_dirname($Dir)} += 1;
7082 }
7083 }
7084 foreach (sort keys(%Prefix))
7085 {
7086 if(get_depth($_)>=3
7087 and $Prefix{$_}==$#Paths+1) {
7088 return 1;
7089 }
7090 }
7091 return 0;
7092}
7093
7094sub isAcceptable($$$)
7095{
7096 my ($Header, $Candidate, $LibVersion) = @_;
7097 my $HName = get_filename($Header);
7098 if(get_dirname($Header))
7099 { # with prefix
7100 return 1;
7101 }
7102 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
7103 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
7104 return 1;
7105 }
7106 if(checkRelevance($Candidate))
7107 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
7108 return 1;
7109 }
7110 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
7111 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
7112 # /usr/include/qt4/Qt/qsslconfiguration.h
7113 return 1;
7114 }
7115 if($OStarget eq "symbian")
7116 {
7117 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
7118 return 1;
7119 }
7120 }
7121 return 0;
7122}
7123
7124sub isRelevant($$$)
7125{ # disallow to search for "abstract" headers in too deep directories
7126 my ($Header, $Candidate, $LibVersion) = @_;
7127 my $HName = get_filename($Header);
7128 if($OStarget eq "symbian")
7129 {
7130 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7131 return 0;
7132 }
7133 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007134 if($OStarget ne "bsd")
7135 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007136 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7137 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7138 return 0;
7139 }
7140 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007141 if($OStarget ne "windows")
7142 {
7143 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7144 { # skip /usr/include/wine/msvcrt
7145 return 0;
7146 }
7147 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007148 if(not get_dirname($Header)
7149 and $Candidate=~/[\/\\]wx[\/\\]/)
7150 { # do NOT search in system /wx/ directory
7151 # for headers without a prefix: sstream.h
7152 return 0;
7153 }
7154 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7155 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7156 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7157 return 0;
7158 }
7159 if($Candidate=~/[\/\\]asm-/
7160 and (my $Arch = getArch($LibVersion)) ne "unknown")
7161 { # arch-specific header files
7162 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7163 {# skip ../asm-arm/ if using x86 architecture
7164 return 0;
7165 }
7166 }
7167 my @Candidates = getSystemHeaders($HName, $LibVersion);
7168 if($#Candidates==1)
7169 { # unique header
7170 return 1;
7171 }
7172 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7173 if($#SCandidates==1)
7174 { # unique name
7175 return 1;
7176 }
7177 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7178 if(get_depth($Candidate)-$SystemDepth>=5)
7179 { # abstract headers in too deep directories
7180 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7181 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7182 return 0;
7183 }
7184 }
7185 if($Header eq "parser.h"
7186 and $Candidate!~/\/libxml2\//)
7187 { # select parser.h from xml2 library
7188 return 0;
7189 }
7190 if(not get_dirname($Header)
7191 and keys(%{$SystemHeaders{$HName}})>=3)
7192 { # many headers with the same name
7193 # like thread.h included without a prefix
7194 if(not checkFamily(@Candidates)) {
7195 return 0;
7196 }
7197 }
7198 return 1;
7199}
7200
7201sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007202{ # cache function
7203 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7204 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7205 }
7206 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7207}
7208
7209sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007210{
7211 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007212 if(-f $Header) {
7213 return $Header;
7214 }
7215 if(is_abs($Header) and not -f $Header)
7216 { # incorrect absolute path
7217 return "";
7218 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007219 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007220 { # too abstract configuration headers
7221 return "";
7222 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007223 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007224 if($OSgroup ne "windows")
7225 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007226 if(defined $WinHeaders{lc($HName)}
7227 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007228 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007229 return "";
7230 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007231 }
7232 if($OSgroup ne "macos")
7233 {
7234 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007235 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007236 return "";
7237 }
7238 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007239
7240 if(defined $ObsoleteHeaders{$HName})
7241 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007242 return "";
7243 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007244 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7245 {
7246 if(defined $AlienHeaders{$HName}
7247 or defined $AlienHeaders{$Header})
7248 { # alien headers from other systems
7249 return "";
7250 }
7251 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007252
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007253 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007254 { # search in default paths
7255 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007256 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007257 }
7258 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007259 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007260 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007261 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007262 }
7263 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7264 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7265 {
7266 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007267 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007268 }
7269 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007270 # error
7271 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007272}
7273
7274sub getSystemHeaders($$)
7275{
7276 my ($Header, $LibVersion) = @_;
7277 my @Candidates = ();
7278 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7279 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007280 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007281 next;
7282 }
7283 push(@Candidates, $Candidate);
7284 }
7285 return @Candidates;
7286}
7287
7288sub cut_path_prefix($$)
7289{
7290 my ($Path, $Prefix) = @_;
7291 return $Path if(not $Prefix);
7292 $Prefix=~s/[\/\\]+\Z//;
7293 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7294 return $Path;
7295}
7296
7297sub is_default_include_dir($)
7298{
7299 my $Dir = $_[0];
7300 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007301 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007302}
7303
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007304sub identifyHeader($$)
7305{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007306 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007307 if(not $Header) {
7308 return "";
7309 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007310 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007311 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7312 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007313 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007314 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007315}
7316
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007317sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007318{ # search for header by absolute path, relative path or name
7319 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007320 if(-f $Header)
7321 { # it's relative or absolute path
7322 return get_abs_path($Header);
7323 }
7324 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7325 and my $HeaderDir = find_in_defaults($Header))
7326 { # search for libc headers in the /usr/include
7327 # for non-libc target library before searching
7328 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007329 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007330 }
7331 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7332 { # search in the target library paths
7333 return $Path;
7334 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007335 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007336 { # search in the internal GCC include paths
7337 return $DefaultGccHeader{$Header};
7338 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007339 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007340 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007341 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007342 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007343 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007344 { # search in the default G++ include paths
7345 return $DefaultCppHeader{$Header};
7346 }
7347 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7348 { # search everywhere in the system
7349 return $AnyPath;
7350 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007351 elsif($OSgroup eq "macos")
7352 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7353 if(my $Dir = get_dirname($Header))
7354 {
7355 my $RelPath = "Headers\/".get_filename($Header);
7356 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007357 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007358 }
7359 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007360 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007361 # cannot find anything
7362 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007363}
7364
7365sub getLocation($)
7366{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007367 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7368 {
7369 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007370 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007372 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007373 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007374}
7375
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007376sub getNameByInfo($)
7377{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007378 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007379 {
7380 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7381 {
7382 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7383 {
7384 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7385 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007386 my $Str = $1;
7387 if($CppMode{$Version}
7388 and $Str=~/\Ac99_(.+)\Z/)
7389 {
7390 if($CppKeywords_A{$1}) {
7391 $Str=$1;
7392 }
7393 }
7394 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007395 }
7396 }
7397 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007398 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007399 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007400}
7401
7402sub getTreeStr($)
7403{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007404 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007405 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007406 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7407 {
7408 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007409 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007410 and $Str=~/\Ac99_(.+)\Z/)
7411 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007412 if($CppKeywords_A{$1}) {
7413 $Str=$1;
7414 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007415 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007416 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007417 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007418 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007419 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007420}
7421
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007422sub getFuncShortName($)
7423{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007424 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007425 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007426 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007427 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007428 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007429 {
7430 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7431 {
7432 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7433 return "operator ".$RName;
7434 }
7435 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007436 }
7437 else
7438 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007439 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7440 {
7441 if(my $Ind = $Operator_Indication{$1}) {
7442 return "operator".$Ind;
7443 }
7444 elsif(not $UnknownOperator{$1})
7445 {
7446 printMsg("WARNING", "unknown operator $1");
7447 $UnknownOperator{$1} = 1;
7448 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007449 }
7450 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007451 }
7452 else
7453 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007454 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7455 return getTreeStr($1);
7456 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007457 }
7458 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007459 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007460}
7461
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007462sub getFuncReturn($)
7463{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007464 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7465 {
7466 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7467 {
7468 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7469 return $1;
7470 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007471 }
7472 }
7473 return "";
7474}
7475
7476sub getFuncOrig($)
7477{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007478 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7479 {
7480 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7481 return $1;
7482 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007483 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007484 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007485}
7486
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007487sub unmangleArray(@)
7488{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007489 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007490 { # MSVC mangling
7491 my $UndNameCmd = get_CmdPath("undname");
7492 if(not $UndNameCmd) {
7493 exitStatus("Not_Found", "can't find \"undname\"");
7494 }
7495 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007496 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007497 }
7498 else
7499 { # GCC mangling
7500 my $CppFiltCmd = get_CmdPath("c++filt");
7501 if(not $CppFiltCmd) {
7502 exitStatus("Not_Found", "can't find c++filt in PATH");
7503 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007504 if(not defined $CPPFILT_SUPPORT_FILE)
7505 {
7506 my $Info = `$CppFiltCmd -h 2>&1`;
7507 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7508 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007509 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007510 if($CPPFILT_SUPPORT_FILE)
7511 { # new versions of c++filt can take a file
7512 if($#_>$MAX_CPPFILT_FILE_SIZE)
7513 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7514 # this is fixed in the oncoming version of Binutils
7515 my @Half = splice(@_, 0, ($#_+1)/2);
7516 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007517 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007518 else
7519 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007520 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7521 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7522 if($?==139)
7523 { # segmentation fault
7524 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7525 }
7526 return split(/\n/, $Res);
7527 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007528 }
7529 else
7530 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007531 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7532 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007533 my @Half = splice(@_, 0, ($#_+1)/2);
7534 return (unmangleArray(@Half), unmangleArray(@_))
7535 }
7536 else
7537 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007538 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007539 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7540 if($?==139)
7541 { # segmentation fault
7542 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7543 }
7544 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007545 }
7546 }
7547 }
7548}
7549
7550sub get_SignatureNoInfo($$)
7551{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007552 my ($Symbol, $LibVersion) = @_;
7553 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
7554 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007555 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007556 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007557 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007558 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007559 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04007560 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007561 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
7562 $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;
7563 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007564 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007565 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007566 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007567 $Signature .= " [data]";
7568 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007569 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007570 $Signature .= " (...)";
7571 }
7572 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007573 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007574 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04007575 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007576 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
7577 }
7578 if($SymbolVersion) {
7579 $Signature .= $VersionSpec.$SymbolVersion;
7580 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007581 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007582}
7583
7584sub get_ChargeLevel($$)
7585{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007586 my ($Symbol, $LibVersion) = @_;
7587 return "" if($Symbol!~/\A(_Z|\?)/);
7588 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7589 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007590 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007591 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007592 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007593 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007594 return "[in-charge]";
7595 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007596 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007597 return "[not-in-charge]";
7598 }
7599 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007600 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007601 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007602 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007603 return "[in-charge]";
7604 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007605 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007606 return "[not-in-charge]";
7607 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007608 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007609 return "[in-charge-deleting]";
7610 }
7611 }
7612 }
7613 else
7614 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007615 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007616 return "[in-charge]";
7617 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007618 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007619 return "[not-in-charge]";
7620 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007621 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007622 return "[in-charge]";
7623 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007624 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007625 return "[not-in-charge]";
7626 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007627 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007628 return "[in-charge-deleting]";
7629 }
7630 }
7631 return "";
7632}
7633
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007634sub get_Signature_M($$)
7635{
7636 my ($Symbol, $LibVersion) = @_;
7637 my $Signature_M = $tr_name{$Symbol};
7638 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7639 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007640 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007641 }
7642 return $Signature_M;
7643}
7644
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007645sub get_Signature($$)
7646{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007647 my ($Symbol, $LibVersion) = @_;
7648 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7649 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007650 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007651 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
7652 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007653 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007654 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007655 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007656 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007657 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7658 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007659 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007660 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7661 {
7662 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7663 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7664 $Signature .= "~";
7665 }
7666 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007667 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007668 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007669 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007670 }
7671 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007672 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007673 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007674 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7675 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007676 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007677 else
7678 {
7679 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007680 }
7681 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007682 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007683 {
7684 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007685 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007686 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007687 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007688 if(not $ParamTypeName) {
7689 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7690 }
7691 foreach my $Typedef (keys(%ChangedTypedef))
7692 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007693 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7694 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7695 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007696 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007697 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7698 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007699 if($ParamName eq "this"
7700 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007701 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007702 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007703 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007704 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007705 }
7706 else {
7707 push(@ParamArray, $ParamTypeName);
7708 }
7709 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007710 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7711 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007712 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007713 }
7714 else
7715 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007716 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007717 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007718 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007719 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007720 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007721 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7722 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007723 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007724 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007725 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7726 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007727 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007728 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007729 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7730 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007731 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007732 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007733 }
7734 }
7735 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007736 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007737 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007738 }
7739 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007740 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007741 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007742 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007743}
7744
7745sub create_member_decl($$)
7746{
7747 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007748 if($TName=~/\([\*]+\)/)
7749 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007750 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7751 return $TName;
7752 }
7753 else
7754 {
7755 my @ArraySizes = ();
7756 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7757 push(@ArraySizes, $1);
7758 }
7759 return $TName." ".$Member.join("", @ArraySizes);
7760 }
7761}
7762
7763sub getFuncType($)
7764{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007765 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7766 {
7767 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7768 {
7769 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7770 {
7771 if($Type eq "method_type") {
7772 return "Method";
7773 }
7774 elsif($Type eq "function_type") {
7775 return "Function";
7776 }
7777 else {
7778 return "Other";
7779 }
7780 }
7781 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007782 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007783 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007784}
7785
7786sub getFuncTypeId($)
7787{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007788 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7789 {
7790 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7791 return $1;
7792 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007793 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007794 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007795}
7796
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007797sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007798{ # "._N" or "$_N" in older GCC versions
7799 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007800}
7801
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007802sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007803{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007804 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7805 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007806 }
7807
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007808 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007809
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007810 if($_[1] ne "S")
7811 {
7812 $N=~s/\A[ ]+//g;
7813 $N=~s/[ ]+\Z//g;
7814 $N=~s/[ ]{2,}/ /g;
7815 }
7816
7817 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007818
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007819 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007820
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007821 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7822 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007823
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007824 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007825
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007826 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007827
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007828 if($_[1] eq "S")
7829 {
7830 if(index($N, "operator")!=-1) {
7831 $N=~s/\b(operator[ ]*)> >/$1>>/;
7832 }
7833 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007834
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007835 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007836}
7837
7838sub get_HeaderDeps($$)
7839{
7840 my ($AbsPath, $LibVersion) = @_;
7841 return () if(not $AbsPath or not $LibVersion);
7842 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7843 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7844 }
7845 my %IncDir = ();
7846 detect_recursive_includes($AbsPath, $LibVersion);
7847 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7848 {
7849 next if(not $HeaderPath);
7850 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7851 my $Dir = get_dirname($HeaderPath);
7852 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7853 {
7854 my $Dep = $Dir;
7855 if($Prefix)
7856 {
7857 if($OSgroup eq "windows")
7858 { # case insensitive seach on windows
7859 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7860 next;
7861 }
7862 }
7863 elsif($OSgroup eq "macos")
7864 { # seach in frameworks
7865 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7866 {
7867 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7868 {# frameworks
7869 my ($HFramework, $HName) = ($1, $2);
7870 $Dep = $HFramework;
7871 }
7872 else
7873 {# mismatch
7874 next;
7875 }
7876 }
7877 }
7878 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7879 { # Linux, FreeBSD
7880 next;
7881 }
7882 }
7883 if(not $Dep)
7884 { # nothing to include
7885 next;
7886 }
7887 if(is_default_include_dir($Dep))
7888 { # included by the compiler
7889 next;
7890 }
7891 if(get_depth($Dep)==1)
7892 { # too short
7893 next;
7894 }
7895 if(isLibcDir($Dep))
7896 { # do NOT include /usr/include/{sys,bits}
7897 next;
7898 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007899 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007900 }
7901 }
7902 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7903 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7904}
7905
7906sub sortIncPaths($$)
7907{
7908 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007909 if(not $ArrRef or $#{$ArrRef}<0) {
7910 return $ArrRef;
7911 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007912 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7913 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007914 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007915 return $ArrRef;
7916}
7917
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007918sub sortDeps($$$)
7919{
7920 if($Header_Dependency{$_[2]}{$_[0]}
7921 and not $Header_Dependency{$_[2]}{$_[1]}) {
7922 return 1;
7923 }
7924 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7925 and $Header_Dependency{$_[2]}{$_[1]}) {
7926 return -1;
7927 }
7928 return 0;
7929}
7930
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007931sub join_P($$)
7932{
7933 my $S = "/";
7934 if($OSgroup eq "windows") {
7935 $S = "\\";
7936 }
7937 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007938}
7939
7940sub get_namespace_additions($)
7941{
7942 my $NameSpaces = $_[0];
7943 my ($Additions, $AddNameSpaceId) = ("", 1);
7944 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7945 {
7946 next if($SkipNameSpaces{$Version}{$NS});
7947 next if(not $NS or $NameSpaces->{$NS}==-1);
7948 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7949 next if($NS=~/\A__/i);
7950 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007951 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007952 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7953 my @NS_Parts = split(/::/, $NS);
7954 next if($#NS_Parts==-1);
7955 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7956 foreach my $NS_Part (@NS_Parts)
7957 {
7958 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7959 $TypeDecl_Suffix .= "}";
7960 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007961 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007962 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7963 $Additions.=" $TypeDecl\n $FuncDecl\n";
7964 $AddNameSpaceId+=1;
7965 }
7966 return $Additions;
7967}
7968
7969sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007970{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007971 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007972 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007973 if($Fmt eq "windows")
7974 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007975 $Path=~s/\//\\/g;
7976 $Path=lc($Path);
7977 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007978 else
7979 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007980 $Path=~s/\\/\//g;
7981 }
7982 return $Path;
7983}
7984
7985sub inc_opt($$)
7986{
7987 my ($Path, $Style) = @_;
7988 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007989 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007990 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007991 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007992 return "-I\"".path_format($Path, "unix")."\"";
7993 }
7994 elsif($OSgroup eq "macos"
7995 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007996 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007997 return "-F".esc(get_dirname($Path));
7998 }
7999 else {
8000 return "-I".esc($Path);
8001 }
8002 }
8003 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008004 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008005 }
8006 return "";
8007}
8008
8009sub platformSpecs($)
8010{
8011 my $LibVersion = $_[0];
8012 my $Arch = getArch($LibVersion);
8013 if($OStarget eq "symbian")
8014 { # options for GCCE compiler
8015 my %Symbian_Opts = map {$_=>1} (
8016 "-D__GCCE__",
8017 "-DUNICODE",
8018 "-fexceptions",
8019 "-D__SYMBIAN32__",
8020 "-D__MARM_INTERWORK__",
8021 "-D_UNICODE",
8022 "-D__S60_50__",
8023 "-D__S60_3X__",
8024 "-D__SERIES60_3X__",
8025 "-D__EPOC32__",
8026 "-D__MARM__",
8027 "-D__EABI__",
8028 "-D__MARM_ARMV5__",
8029 "-D__SUPPORT_CPP_EXCEPTIONS__",
8030 "-march=armv5t",
8031 "-mapcs",
8032 "-mthumb-interwork",
8033 "-DEKA2",
8034 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
8035 );
8036 return join(" ", keys(%Symbian_Opts));
8037 }
8038 elsif($OSgroup eq "windows"
8039 and get_dumpmachine($GCC_PATH)=~/mingw/i)
8040 { # add options to MinGW compiler
8041 # to simulate the MSVC compiler
8042 my %MinGW_Opts = map {$_=>1} (
8043 "-D_WIN32",
8044 "-D_STDCALL_SUPPORTED",
8045 "-D__int64=\"long long\"",
8046 "-D__int32=int",
8047 "-D__int16=short",
8048 "-D__int8=char",
8049 "-D__possibly_notnullterminated=\" \"",
8050 "-D__nullterminated=\" \"",
8051 "-D__nullnullterminated=\" \"",
8052 "-D__w64=\" \"",
8053 "-D__ptr32=\" \"",
8054 "-D__ptr64=\" \"",
8055 "-D__forceinline=inline",
8056 "-D__inline=inline",
8057 "-D__uuidof(x)=IID()",
8058 "-D__try=",
8059 "-D__except(x)=",
8060 "-D__declspec(x)=__attribute__((x))",
8061 "-D__pragma(x)=",
8062 "-D_inline=inline",
8063 "-D__forceinline=__inline",
8064 "-D__stdcall=__attribute__((__stdcall__))",
8065 "-D__cdecl=__attribute__((__cdecl__))",
8066 "-D__fastcall=__attribute__((__fastcall__))",
8067 "-D__thiscall=__attribute__((__thiscall__))",
8068 "-D_stdcall=__attribute__((__stdcall__))",
8069 "-D_cdecl=__attribute__((__cdecl__))",
8070 "-D_fastcall=__attribute__((__fastcall__))",
8071 "-D_thiscall=__attribute__((__thiscall__))",
8072 "-DSHSTDAPI_(x)=x",
8073 "-D_MSC_EXTENSIONS",
8074 "-DSECURITY_WIN32",
8075 "-D_MSC_VER=1500",
8076 "-D_USE_DECLSPECS_FOR_SAL",
8077 "-D__noop=\" \"",
8078 "-DDECLSPEC_DEPRECATED=\" \"",
8079 "-D__builtin_alignof(x)=__alignof__(x)",
8080 "-DSORTPP_PASS");
8081 if($Arch eq "x86") {
8082 $MinGW_Opts{"-D_M_IX86=300"}=1;
8083 }
8084 elsif($Arch eq "x86_64") {
8085 $MinGW_Opts{"-D_M_AMD64=300"}=1;
8086 }
8087 elsif($Arch eq "ia64") {
8088 $MinGW_Opts{"-D_M_IA64=300"}=1;
8089 }
8090 return join(" ", keys(%MinGW_Opts));
8091 }
8092 return "";
8093}
8094
8095my %C_Structure = map {$_=>1} (
8096# FIXME: Can't separate union and struct data types before dumping,
8097# so it sometimes cause compilation errors for unknown reason
8098# when trying to declare TYPE* tmp_add_class_N
8099# This is a list of such structures + list of other C structures
8100 "sigval",
8101 "sigevent",
8102 "sigaction",
8103 "sigvec",
8104 "sigstack",
8105 "timeval",
8106 "timezone",
8107 "rusage",
8108 "rlimit",
8109 "wait",
8110 "flock",
8111 "stat",
8112 "_stat",
8113 "stat32",
8114 "_stat32",
8115 "stat64",
8116 "_stat64",
8117 "_stati64",
8118 "if_nameindex",
8119 "usb_device",
8120 "sigaltstack",
8121 "sysinfo",
8122 "timeLocale",
8123 "tcp_debug",
8124 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008125 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008126 "timespec",
8127 "random_data",
8128 "drand48_data",
8129 "_IO_marker",
8130 "_IO_FILE",
8131 "lconv",
8132 "sched_param",
8133 "tm",
8134 "itimerspec",
8135 "_pthread_cleanup_buffer",
8136 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008137 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008138 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008139 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008140 "sigcontext",
8141 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008142 # Mac
8143 "_timex",
8144 "_class_t",
8145 "_category_t",
8146 "_class_ro_t",
8147 "_protocol_t",
8148 "_message_ref_t",
8149 "_super_message_ref_t",
8150 "_ivar_t",
8151 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008152);
8153
8154sub getCompileCmd($$$)
8155{
8156 my ($Path, $Opt, $Inc) = @_;
8157 my $GccCall = $GCC_PATH;
8158 if($Opt) {
8159 $GccCall .= " ".$Opt;
8160 }
8161 $GccCall .= " -x ";
8162 if($OSgroup eq "macos") {
8163 $GccCall .= "objective-";
8164 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008165
8166 if($EMERGENCY_MODE_48)
8167 { # workaround for GCC 4.8 (C only)
8168 $GccCall .= "c++";
8169 }
8170 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008171 { # compile as "C++" header
8172 # to obtain complete dump using GCC 4.0
8173 $GccCall .= "c++-header";
8174 }
8175 else
8176 { # compile as "C++" source
8177 # GCC 3.3 cannot compile headers
8178 $GccCall .= "c++";
8179 }
8180 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008181 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008182 $GccCall .= " ".$Opts;
8183 }
8184 # allow extra qualifications
8185 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008186 $GccCall .= " -fpermissive";
8187 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008188 if($NoStdInc)
8189 {
8190 $GccCall .= " -nostdinc";
8191 $GccCall .= " -nostdinc++";
8192 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008193 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008194 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008195 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008196 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008197 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008198 if($Inc)
8199 { # include paths
8200 $GccCall .= " ".$Inc;
8201 }
8202 return $GccCall;
8203}
8204
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008205sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008206{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008207 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008208 my %HeaderElems = (
8209 # Types
8210 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008211 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008212 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8213 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008214 "time.h" => ["time_t"],
8215 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008216 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8217 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008218 "stdbool.h" => ["_Bool"],
8219 "rpc/xdr.h" => ["bool_t"],
8220 "in_systm.h" => ["n_long", "n_short"],
8221 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008222 "arpa/inet.h" => ["fw_src", "ip_src"],
8223 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008224 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008225 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008226 );
8227 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008228 foreach (keys(%HeaderElems))
8229 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008230 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008231 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008232 }
8233 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008234 my %Types = ();
8235 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8236 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008237 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008238 }
8239 if(keys(%Types))
8240 {
8241 my %AddHeaders = ();
8242 foreach my $Type (keys(%Types))
8243 {
8244 if(my $Header = $AutoPreamble{$Type})
8245 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008246 if(my $Path = identifyHeader($Header, $LibVersion))
8247 {
8248 if(skipHeader($Path, $LibVersion)) {
8249 next;
8250 }
8251 $Path = path_format($Path, $OSgroup);
8252 $AddHeaders{$Path}{"Type"} = $Type;
8253 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008254 }
8255 }
8256 }
8257 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008258 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008259 }
8260 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008261 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008262}
8263
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008264sub checkCTags($)
8265{
8266 my $Path = $_[0];
8267 if(not $Path) {
8268 return;
8269 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008270 my $CTags = undef;
8271
8272 if($OSgroup eq "bsd")
8273 { # use ectags on BSD
8274 $CTags = get_CmdPath("ectags");
8275 if(not $CTags) {
8276 printMsg("WARNING", "can't find \'ectags\' program");
8277 }
8278 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008279 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008280 $CTags = get_CmdPath("ctags");
8281 }
8282 if(not $CTags)
8283 {
8284 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008285 return;
8286 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008287
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008288 if($OSgroup ne "linux")
8289 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008290 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8291 if($Info!~/exuberant/i)
8292 {
8293 printMsg("WARNING", "incompatible version of \'ctags\' program");
8294 return;
8295 }
8296 }
8297
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008298 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008299 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008300 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008301 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008302 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008303 open(CTAGS, "<", $Out);
8304 while(my $Line = <CTAGS>)
8305 {
8306 chomp($Line);
8307 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008308 if(defined $Intrinsic_Keywords{$Name})
8309 { # noise
8310 next;
8311 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008312 if($Type eq "n")
8313 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008314 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008315 next;
8316 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008317 if(index($Scpe, "struct:")==0) {
8318 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008319 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008320 if(index($Scpe, "namespace:")==0)
8321 {
8322 if($Scpe=~s/\Anamespace://) {
8323 $Name = $Scpe."::".$Name;
8324 }
8325 }
8326 $TUnit_NameSpaces{$Version}{$Name} = 1;
8327 }
8328 elsif($Type eq "p")
8329 {
8330 if(not $Scpe or index($Scpe, "namespace:")==0) {
8331 $TUnit_Funcs{$Version}{$Name} = 1;
8332 }
8333 }
8334 elsif($Type eq "x")
8335 {
8336 if(not $Scpe or index($Scpe, "namespace:")==0) {
8337 $TUnit_Vars{$Version}{$Name} = 1;
8338 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008339 }
8340 }
8341 close(CTAGS);
8342}
8343
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008344sub preChange($$)
8345{
8346 my ($HeaderPath, $IncStr) = @_;
8347
8348 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8349 my $Content = undef;
8350
8351 if($OStarget eq "windows"
8352 and get_dumpmachine($GCC_PATH)=~/mingw/i
8353 and $MinGWMode{$Version}!=-1)
8354 { # modify headers to compile by MinGW
8355 if(not $Content)
8356 { # preprocessing
8357 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8358 }
8359 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8360 { # __asm { ... }
8361 $MinGWMode{$Version}=1;
8362 }
8363 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8364 { # comments after preprocessing
8365 $MinGWMode{$Version}=1;
8366 }
8367 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8368 { # 0xffui8
8369 $MinGWMode{$Version}=1;
8370 }
8371
8372 if($MinGWMode{$Version}) {
8373 printMsg("INFO", "Using MinGW compatibility mode");
8374 }
8375 }
8376
8377 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8378 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8379 { # rename C++ keywords in C code
8380 # disable this code by -cpp-compatible option
8381 if(not $Content)
8382 { # preprocessing
8383 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8384 }
8385 my $RegExp_C = join("|", keys(%CppKeywords_C));
8386 my $RegExp_F = join("|", keys(%CppKeywords_F));
8387 my $RegExp_O = join("|", keys(%CppKeywords_O));
8388
8389 my $Detected = undef;
8390
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008391 while($Content=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*([\,\)\;\.\[]|\-\>|\:\s*\d))/$1$2c99_$3$4/g)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008392 { # MATCH:
8393 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008394 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008395 # unsigned private: 8;
8396 # DO NOT MATCH:
8397 # #pragma GCC visibility push(default)
8398 $CppMode{$Version} = 1;
8399 $Detected = "$1$2$3$4" if(not defined $Detected);
8400 }
8401 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8402 { # MATCH:
8403 # int delete(...);
8404 # int explicit(...);
8405 # DO NOT MATCH:
8406 # void operator delete(...)
8407 $CppMode{$Version} = 1;
8408 $Detected = "$1$2$3" if(not defined $Detected);
8409 }
8410 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8411 { # MATCH:
8412 # int bool;
8413 # DO NOT MATCH:
8414 # bool X;
8415 # return *this;
8416 # throw;
8417 $CppMode{$Version} = 1;
8418 $Detected = "$1$2$3" if(not defined $Detected);
8419 }
8420 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8421 { # MATCH:
8422 # int operator(...);
8423 # DO NOT MATCH:
8424 # int operator()(...);
8425 $CppMode{$Version} = 1;
8426 $Detected = "$1$2$3" if(not defined $Detected);
8427 }
8428 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8429 { # MATCH:
8430 # int foo(int operator);
8431 # int foo(int operator, int other);
8432 # DO NOT MATCH:
8433 # int operator,(...);
8434 $CppMode{$Version} = 1;
8435 $Detected = "$1$2$3" if(not defined $Detected);
8436 }
8437 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8438 { # MATCH:
8439 # int foo(gboolean *bool);
8440 # DO NOT MATCH:
8441 # void setTabEnabled(int index, bool);
8442 $CppMode{$Version} = 1;
8443 $Detected = "$1$2$3" if(not defined $Detected);
8444 }
8445 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8446 { # MATCH:
8447 # int foo(int* this);
8448 # int bar(int this);
8449 # int baz(int throw);
8450 # DO NOT MATCH:
8451 # foo(X, this);
8452 $CppMode{$Version} = 1;
8453 $Detected = "$1$2$3$4" if(not defined $Detected);
8454 }
8455 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8456 { # MATCH:
8457 # struct template {...};
8458 # extern template foo(...);
8459 $CppMode{$Version} = 1;
8460 $Detected = "$1$2" if(not defined $Detected);
8461 }
8462
8463 if($CppMode{$Version} == 1)
8464 {
8465 if($Debug)
8466 {
8467 $Detected=~s/\A\s+//g;
8468 printMsg("INFO", "Detected code: \"$Detected\"");
8469 }
8470 }
8471
8472 # remove typedef enum NAME NAME;
8473 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8474 my $N = 0;
8475 while($N<=$#FwdTypedefs-1)
8476 {
8477 my $S = $FwdTypedefs[$N];
8478 if($S eq $FwdTypedefs[$N+1])
8479 {
8480 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008481 $CppMode{$Version} = 1;
8482
8483 if($Debug) {
8484 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8485 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008486 }
8487 $N+=2;
8488 }
8489
8490 if($CppMode{$Version}==1) {
8491 printMsg("INFO", "Using C++ compatibility mode");
8492 }
8493 }
8494
8495 if($CppMode{$Version}==1
8496 or $MinGWMode{$Version}==1)
8497 {
8498 my $IPath = $TMP_DIR."/dump$Version.i";
8499 writeFile($IPath, $Content);
8500 return $IPath;
8501 }
8502
8503 return undef;
8504}
8505
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008506sub getDump()
8507{
8508 if(not $GCC_PATH) {
8509 exitStatus("Error", "internal error - GCC path is not set");
8510 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008511
8512 my @Headers = keys(%{$Registered_Headers{$Version}});
8513 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8514
8515 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8516
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008517 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008518 my $HeaderPath = $TmpHeaderPath;
8519
8520 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008521 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008522 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8523 {
8524 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008525 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008526 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008527 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008528 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8529 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008530 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008531 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008532 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008533 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8534 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8535 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008536 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008537 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008538
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008539 if($ExtraInfo)
8540 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008541 if($IncludeString) {
8542 writeFile($ExtraInfo."/include-string", $IncludeString);
8543 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008544 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8545 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008546
8547 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8548 {
8549 my $REDIR = "";
8550 foreach my $P1 (sort @Redirects) {
8551 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8552 }
8553 writeFile($ExtraInfo."/include-redirect", $REDIR);
8554 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008555 }
8556
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008557 if(not keys(%{$TargetHeaders{$Version}}))
8558 { # Target headers
8559 addTargetHeaders($Version);
8560 }
8561
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008562 # clean memory
8563 %RecursiveIncludes = ();
8564 %Header_Include_Prefix = ();
8565 %Header_Includes = ();
8566
8567 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008568 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008569 delete($Cache{"detect_header_includes"});
8570 delete($Cache{"selectSystemHeader"});
8571
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008572 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008573 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8574 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008575
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008576 if($ExtraInfo)
8577 { # extra information for other tools
8578 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8579 }
8580
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008581 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008582 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008583 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008584
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008585 if($COMMON_LANGUAGE{$Version} eq "C++") {
8586 checkCTags($Pre);
8587 }
8588
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008589 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8590 { # try to correct the preprocessor output
8591 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008592 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008593
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008594 if($COMMON_LANGUAGE{$Version} eq "C++")
8595 { # add classes and namespaces to the dump
8596 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008597 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008598 or $MinGWMode{$Version}==1) {
8599 $CHdump .= " -fpreprocessed";
8600 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008601 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008602 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008603 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008604 chdir($ORIG_DIR);
8605 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8606 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008607 my $Content = readFile($ClassDump);
8608 foreach my $ClassInfo (split(/\n\n/, $Content))
8609 {
8610 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8611 {
8612 my $CName = $1;
8613 next if($CName=~/\A(__|_objc_|_opaque_)/);
8614 $TUnit_NameSpaces{$Version}{$CName} = -1;
8615 if($CName=~/\A[\w:]+\Z/)
8616 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008617 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008618 }
8619 if($CName=~/(\w[\w:]*)::/)
8620 { # namespaces
8621 my $NS = $1;
8622 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8623 $TUnit_NameSpaces{$Version}{$NS} = 1;
8624 }
8625 }
8626 }
8627 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8628 { # read v-tables (advanced approach)
8629 my ($CName, $VTable) = ($1, $2);
8630 $ClassVTable_Content{$Version}{$CName} = $VTable;
8631 }
8632 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008633 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8634 { # add user-defined namespaces
8635 $TUnit_NameSpaces{$Version}{$NS} = 1;
8636 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008637 if($Debug)
8638 { # debug mode
8639 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008640 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008641 }
8642 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008643 }
8644
8645 # add namespaces and classes
8646 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8647 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008648 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008649 }
8650 # some GCC versions don't include class methods to the TU dump by default
8651 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008652 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008653 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8654 {
8655 next if($C_Structure{$CName});
8656 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008657 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008658 if(not $Force and $GCC_44
8659 and $OSgroup eq "linux")
8660 { # optimization for linux with GCC >= 4.4
8661 # disable this code by -force option
8662 if(index($CName, "::")!=-1)
8663 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008664 next;
8665 }
8666 }
8667 else
8668 {
8669 if($CName=~/\A(.+)::[^:]+\Z/
8670 and $TUnit_Classes{$Version}{$1})
8671 { # classes inside other classes
8672 next;
8673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008674 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008675 if(defined $TUnit_Funcs{$Version}{$CName})
8676 { # the same name for a function and type
8677 next;
8678 }
8679 if(defined $TUnit_Vars{$Version}{$CName})
8680 { # the same name for a variable and type
8681 next;
8682 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008683 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8684 }
8685 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008686 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008687 }
8688 }
8689 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8690 # create TU dump
8691 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008692 if($UserLang eq "C") {
8693 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8694 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008695 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008696 or $MinGWMode{$Version}==1) {
8697 $TUdump .= " -fpreprocessed";
8698 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008699 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008700 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8701 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008702 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008703 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008704 if($?)
8705 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008706 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008707 { # try to recompile
8708 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008709 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008710 and index($Errors, "c99_")!=-1
8711 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008712 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008713 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008714
8715 if($Debug)
8716 {
8717 # printMsg("INFO", $Errors);
8718 }
8719
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008720 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008721 resetLogging($Version);
8722 $TMP_DIR = tempdir(CLEANUP=>1);
8723 return getDump();
8724 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008725 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008726 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008727 { # add auto preamble headers and try again
8728 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008729 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008730 foreach my $Num (0 .. $#Headers)
8731 {
8732 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008733 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8734 {
8735 push_U($Include_Preamble{$Version}, $Path);
8736 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008737 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008738 }
8739 resetLogging($Version);
8740 $TMP_DIR = tempdir(CLEANUP=>1);
8741 return getDump();
8742 }
8743 elsif($Cpp0xMode{$Version}!=-1
8744 and ($Errors=~/\Q-std=c++0x\E/
8745 or $Errors=~/is not a class or namespace/))
8746 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008747 if(check_gcc($GCC_PATH, "4.6"))
8748 {
8749 $Cpp0xMode{$Version}=-1;
8750 printMsg("INFO", "Enabling c++0x mode");
8751 resetLogging($Version);
8752 $TMP_DIR = tempdir(CLEANUP=>1);
8753 $CompilerOptions{$Version} .= " -std=c++0x";
8754 return getDump();
8755 }
8756 else {
8757 printMsg("WARNING", "Probably c++0x construction detected");
8758 }
8759
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008760 }
8761 elsif($MinGWMode{$Version}==1)
8762 { # disable MinGW mode and try again
8763 $MinGWMode{$Version}=-1;
8764 resetLogging($Version);
8765 $TMP_DIR = tempdir(CLEANUP=>1);
8766 return getDump();
8767 }
8768 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008769 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008770 else {
8771 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008772 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008773 printMsg("ERROR", "some errors occurred when compiling headers");
8774 printErrorLog($Version);
8775 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008776 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008777 }
8778 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008779 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008780 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008781
8782 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8783 return $TUs[0];
8784 }
8785 else
8786 {
8787 my $Msg = "can't compile header(s)";
8788 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8789 $Msg .= "\nDid you install G++?";
8790 }
8791 exitStatus("Cannot_Compile", $Msg);
8792 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008793}
8794
8795sub cmd_file($)
8796{
8797 my $Path = $_[0];
8798 return "" if(not $Path or not -e $Path);
8799 if(my $CmdPath = get_CmdPath("file")) {
8800 return `$CmdPath -b \"$Path\"`;
8801 }
8802 return "";
8803}
8804
8805sub getIncString($$)
8806{
8807 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008808 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008809 my $String = "";
8810 foreach (@{$ArrRef}) {
8811 $String .= " ".inc_opt($_, $Style);
8812 }
8813 return $String;
8814}
8815
8816sub getIncPaths(@)
8817{
8818 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008819 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008820 if($INC_PATH_AUTODETECT{$Version})
8821 { # auto-detecting dependencies
8822 my %Includes = ();
8823 foreach my $HPath (@HeaderPaths)
8824 {
8825 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8826 {
8827 if($Skip_Include_Paths{$Version}{$Dir}) {
8828 next;
8829 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008830 if($SystemRoot)
8831 {
8832 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8833 next;
8834 }
8835 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008836 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008837 }
8838 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008839 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008840 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008841 }
8842 }
8843 else
8844 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008845 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008846 }
8847 return \@IncPaths;
8848}
8849
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008850sub push_U($@)
8851{ # push unique
8852 if(my $Array = shift @_)
8853 {
8854 if(@_)
8855 {
8856 my %Exist = map {$_=>1} @{$Array};
8857 foreach my $Elem (@_)
8858 {
8859 if(not defined $Exist{$Elem})
8860 {
8861 push(@{$Array}, $Elem);
8862 $Exist{$Elem} = 1;
8863 }
8864 }
8865 }
8866 }
8867}
8868
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008869sub callPreprocessor($$$)
8870{
8871 my ($Path, $Inc, $LibVersion) = @_;
8872 return "" if(not $Path or not -f $Path);
8873 my $IncludeString=$Inc;
8874 if(not $Inc) {
8875 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8876 }
8877 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008878 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008879 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008880 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008881}
8882
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008883sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008884{ # native "find" is much faster than File::Find (~6x)
8885 # also the File::Find doesn't support --maxdepth N option
8886 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008887 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008888 return () if(not $Path or not -e $Path);
8889 if($OSgroup eq "windows")
8890 {
8891 my $DirCmd = get_CmdPath("dir");
8892 if(not $DirCmd) {
8893 exitStatus("Not_Found", "can't find \"dir\" command");
8894 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008895 $Path = get_abs_path($Path);
8896 $Path = path_format($Path, $OSgroup);
8897 my $Cmd = $DirCmd." \"$Path\" /B /O";
8898 if($MaxDepth!=1) {
8899 $Cmd .= " /S";
8900 }
8901 if($Type eq "d") {
8902 $Cmd .= " /AD";
8903 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008904 elsif($Type eq "f") {
8905 $Cmd .= " /A-D";
8906 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008907 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008908 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008909 {
8910 if(not $UseRegex)
8911 { # FIXME: how to search file names in MS shell?
8912 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008913 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008914 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008915 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008916 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008917 }
8918 my @AbsPaths = ();
8919 foreach my $File (@Files)
8920 {
8921 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008922 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008923 }
8924 if($Type eq "f" and not -f $File)
8925 { # skip dirs
8926 next;
8927 }
8928 push(@AbsPaths, path_format($File, $OSgroup));
8929 }
8930 if($Type eq "d") {
8931 push(@AbsPaths, $Path);
8932 }
8933 return @AbsPaths;
8934 }
8935 else
8936 {
8937 my $FindCmd = get_CmdPath("find");
8938 if(not $FindCmd) {
8939 exitStatus("Not_Found", "can't find a \"find\" command");
8940 }
8941 $Path = get_abs_path($Path);
8942 if(-d $Path and -l $Path
8943 and $Path!~/\/\Z/)
8944 { # for directories that are symlinks
8945 $Path.="/";
8946 }
8947 my $Cmd = $FindCmd." \"$Path\"";
8948 if($MaxDepth) {
8949 $Cmd .= " -maxdepth $MaxDepth";
8950 }
8951 if($Type) {
8952 $Cmd .= " -type $Type";
8953 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008954 if($Name and not $UseRegex)
8955 { # wildcards
8956 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008957 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008958 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008959 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008960 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8961 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008962 my @Files = split(/\n/, $Res);
8963 if($Name and $UseRegex)
8964 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008965 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008966 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008967 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008968 }
8969}
8970
8971sub unpackDump($)
8972{
8973 my $Path = $_[0];
8974 return "" if(not $Path or not -e $Path);
8975 $Path = get_abs_path($Path);
8976 $Path = path_format($Path, $OSgroup);
8977 my ($Dir, $FileName) = separate_path($Path);
8978 my $UnpackDir = $TMP_DIR."/unpack";
8979 rmtree($UnpackDir);
8980 mkpath($UnpackDir);
8981 if($FileName=~s/\Q.zip\E\Z//g)
8982 { # *.zip
8983 my $UnzipCmd = get_CmdPath("unzip");
8984 if(not $UnzipCmd) {
8985 exitStatus("Not_Found", "can't find \"unzip\" command");
8986 }
8987 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008988 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008989 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008990 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008991 }
8992 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008993 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008994 if(not @Contents) {
8995 exitStatus("Error", "can't extract \'$Path\'");
8996 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008997 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008998 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008999 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009000 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04009001 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009002 if($OSgroup eq "windows")
9003 { # -xvzf option is not implemented in tar.exe (2003)
9004 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
9005 my $TarCmd = get_CmdPath("tar");
9006 if(not $TarCmd) {
9007 exitStatus("Not_Found", "can't find \"tar\" command");
9008 }
9009 my $GzipCmd = get_CmdPath("gzip");
9010 if(not $GzipCmd) {
9011 exitStatus("Not_Found", "can't find \"gzip\" command");
9012 }
9013 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04009014 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009015 if($?) {
9016 exitStatus("Error", "can't extract \'$Path\'");
9017 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009018 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009019 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009020 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009021 }
9022 chdir($ORIG_DIR);
9023 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009024 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009025 if(not @Contents) {
9026 exitStatus("Error", "can't extract \'$Path\'");
9027 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009028 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009029 }
9030 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009031 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009032 my $TarCmd = get_CmdPath("tar");
9033 if(not $TarCmd) {
9034 exitStatus("Not_Found", "can't find \"tar\" command");
9035 }
9036 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009037 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009038 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009039 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009040 }
9041 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009042 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009043 if(not @Contents) {
9044 exitStatus("Error", "can't extract \'$Path\'");
9045 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009046 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009047 }
9048 }
9049}
9050
9051sub createArchive($$)
9052{
9053 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009054 if(not $To) {
9055 $To = ".";
9056 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009057 if(not $Path or not -e $Path
9058 or not -d $To) {
9059 return "";
9060 }
9061 my ($From, $Name) = separate_path($Path);
9062 if($OSgroup eq "windows")
9063 { # *.zip
9064 my $ZipCmd = get_CmdPath("zip");
9065 if(not $ZipCmd) {
9066 exitStatus("Not_Found", "can't find \"zip\"");
9067 }
9068 my $Pkg = $To."/".$Name.".zip";
9069 unlink($Pkg);
9070 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04009071 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009072 if($?)
9073 { # cannot allocate memory (or other problems with "zip")
9074 unlink($Path);
9075 exitStatus("Error", "can't pack the ABI dump: ".$!);
9076 }
9077 chdir($ORIG_DIR);
9078 unlink($Path);
9079 return $Pkg;
9080 }
9081 else
9082 { # *.tar.gz
9083 my $TarCmd = get_CmdPath("tar");
9084 if(not $TarCmd) {
9085 exitStatus("Not_Found", "can't find \"tar\"");
9086 }
9087 my $GzipCmd = get_CmdPath("gzip");
9088 if(not $GzipCmd) {
9089 exitStatus("Not_Found", "can't find \"gzip\"");
9090 }
9091 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
9092 unlink($Pkg);
9093 chdir($From);
9094 system($TarCmd, "-czf", $Pkg, $Name);
9095 if($?)
9096 { # cannot allocate memory (or other problems with "tar")
9097 unlink($Path);
9098 exitStatus("Error", "can't pack the ABI dump: ".$!);
9099 }
9100 chdir($ORIG_DIR);
9101 unlink($Path);
9102 return $To."/".$Name.".tar.gz";
9103 }
9104}
9105
9106sub is_header_file($)
9107{
9108 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
9109 return $_[0];
9110 }
9111 return 0;
9112}
9113
9114sub is_not_header($)
9115{
9116 if($_[0]=~/\.\w+\Z/
9117 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
9118 return 1;
9119 }
9120 return 0;
9121}
9122
9123sub is_header($$$)
9124{
9125 my ($Header, $UserDefined, $LibVersion) = @_;
9126 return 0 if(-d $Header);
9127 if(-f $Header) {
9128 $Header = get_abs_path($Header);
9129 }
9130 else
9131 {
9132 if(is_abs($Header))
9133 { # incorrect absolute path
9134 return 0;
9135 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009136 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009137 $Header = $HPath;
9138 }
9139 else
9140 { # can't find header
9141 return 0;
9142 }
9143 }
9144 if($Header=~/\.\w+\Z/)
9145 { # have an extension
9146 return is_header_file($Header);
9147 }
9148 else
9149 {
9150 if($UserDefined==2)
9151 { # specified on the command line
9152 if(cmd_file($Header)!~/HTML|XML/i) {
9153 return $Header;
9154 }
9155 }
9156 elsif($UserDefined)
9157 { # specified in the XML-descriptor
9158 # header file without an extension
9159 return $Header;
9160 }
9161 else
9162 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009163 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009164 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009165 { # !~/HTML|XML|shared|dynamic/i
9166 return $Header;
9167 }
9168 }
9169 }
9170 return 0;
9171}
9172
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009173sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009174{
9175 my $LibVersion = $_[0];
9176 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9177 {
9178 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009179 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009180
9181 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9182 detect_recursive_includes($RegHeader, $LibVersion);
9183 }
9184
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009185 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9186 {
9187 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009188
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009189 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009190 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9191 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009192 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009193 }
9194 }
9195 }
9196}
9197
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009198sub familiarDirs($$)
9199{
9200 my ($D1, $D2) = @_;
9201 if($D1 eq $D2) {
9202 return 1;
9203 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009204
9205 my $U1 = index($D1, "/usr/");
9206 my $U2 = index($D2, "/usr/");
9207
9208 if($U1==0 and $U2!=0) {
9209 return 0;
9210 }
9211
9212 if($U2==0 and $U1!=0) {
9213 return 0;
9214 }
9215
9216 if(index($D2, $D1."/")==0) {
9217 return 1;
9218 }
9219
9220 # /usr/include/DIR
9221 # /home/user/DIR
9222
9223 my $DL = get_depth($D1);
9224
9225 my @Dirs1 = ($D1);
9226 while($DL - get_depth($D1)<=2
9227 and get_depth($D1)>=4
9228 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9229 push(@Dirs1, $D1);
9230 }
9231
9232 my @Dirs2 = ($D2);
9233 while(get_depth($D2)>=4
9234 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9235 push(@Dirs2, $D2);
9236 }
9237
9238 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009239 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009240 foreach my $P2 (@Dirs2)
9241 {
9242
9243 if($P1 eq $P2) {
9244 return 1;
9245 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009246 }
9247 }
9248 return 0;
9249}
9250
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009251sub readHeaders($)
9252{
9253 $Version = $_[0];
9254 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9255 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009256 if($Debug)
9257 { # debug mode
9258 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009259 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009260 }
9261 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009262}
9263
9264sub prepareTypes($)
9265{
9266 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009267 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009268 { # support for old ABI dumps
9269 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009270 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009271 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009272 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9273 if($TName=~/\A(\w+)::(\w+)/) {
9274 my ($P1, $P2) = ($1, $2);
9275 if($P1 eq $P2) {
9276 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009277 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009278 else {
9279 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9280 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009281 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009282 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009283 }
9284 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009285 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009286 { # support for old ABI dumps
9287 # V < 2.5: array size == "number of elements"
9288 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009289 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009290 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009291 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009292 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009293 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009294 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009295 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009296 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009297 $Size *= $Base{"Size"};
9298 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009299 }
9300 else
9301 { # array[] is a pointer
9302 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009303 }
9304 }
9305 }
9306 }
9307 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009308 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009309 { # support for old ABI dumps
9310 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009311 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009312 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009313 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009314 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009315 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009316 my %Type = get_Type($TypeId, $LibVersion);
9317 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9318 my %Type2 = get_Type($TypeId_2, $V2);
9319 if($Type{"Size"} ne $Type2{"Size"}) {
9320 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009321 }
9322 }
9323 }
9324 }
9325}
9326
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009327sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009328{
9329 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009330
9331 if(not keys(%{$SymbolInfo{$LibVersion}}))
9332 { # check if input is valid
9333 if(not $ExtendedCheck and not $CheckObjectsOnly)
9334 {
9335 if($CheckHeadersOnly) {
9336 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9337 }
9338 else {
9339 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9340 }
9341 }
9342 }
9343
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009344 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009345 if(not checkDump(1, "2.10")
9346 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009347 { # different formats
9348 $Remangle = 1;
9349 }
9350 if($CheckHeadersOnly)
9351 { # different languages
9352 if($UserLang)
9353 { # --lang=LANG for both versions
9354 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9355 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9356 {
9357 if($UserLang eq "C++")
9358 { # remangle symbols
9359 $Remangle = 1;
9360 }
9361 elsif($UserLang eq "C")
9362 { # remove mangling
9363 $Remangle = -1;
9364 }
9365 }
9366 }
9367 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009368
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009369 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009370 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009371 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009372 { # support for old ABI dumps
9373 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9374 {
9375 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9376 {
9377 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9378 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009379 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009380 if(defined $DVal and $DVal ne "")
9381 {
9382 if($TName eq "char") {
9383 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9384 }
9385 elsif($TName eq "bool") {
9386 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9387 }
9388 }
9389 }
9390 }
9391 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009392 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009393 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009394 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9395 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009396 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009397 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9398 # + support for old ABI dumps
9399 next;
9400 }
9401 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009402 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009403 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009404 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009405 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009406
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009407 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009408 if(not checkDump(1, "2.12")
9409 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009410 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009411 if($ShortName eq "operator>>")
9412 {
9413 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9414 { # corrected mangling of operator>>
9415 $SRemangle = 1;
9416 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009417 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009418 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9419 {
9420 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9421 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9422 { # corrected mangling of const global data
9423 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9424 # and incorrectly mangled by old ACC versions
9425 $SRemangle = 1;
9426 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009427 }
9428 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009429 if(not $CheckHeadersOnly)
9430 { # support for old ABI dumps
9431 if(not checkDump(1, "2.17")
9432 or not checkDump(2, "2.17"))
9433 {
9434 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9435 {
9436 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9437 {
9438 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9439 {
9440 $MnglName = $ShortName;
9441 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9442 }
9443 }
9444 }
9445 }
9446 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009447 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009448 { # support for old ABI dumps: some symbols are not mangled in old dumps
9449 # mangle both sets of symbols (old and new)
9450 # NOTE: remangling all symbols by the same mangler
9451 if($MnglName=~/\A_ZN(V|)K/)
9452 { # mangling may be incorrect on old ABI dumps
9453 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009454 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009455 }
9456 if($MnglName=~/\A_ZN(K|)V/)
9457 { # mangling may be incorrect on old ABI dumps
9458 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009459 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009460 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009461 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9462 or (not $ClassID and $CheckHeadersOnly)
9463 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9464 { # support for old ABI dumps, GCC >= 4.0
9465 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009466 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009467 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009468 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009469 $MangledNames{$LibVersion}{$MnglName} = 1;
9470 }
9471 }
9472 }
9473 elsif($Remangle==-1)
9474 { # remove mangling
9475 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009476 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009477 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009478 if(not $MnglName) {
9479 next;
9480 }
9481 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9482 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009483 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9484
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009485 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009486 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009487 { # support for old dumps
9488 # add "Volatile" attribute
9489 if($MnglName=~/_Z(K|)V/) {
9490 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9491 }
9492 }
9493 # symbol and its symlink have same signatures
9494 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009495 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009496 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009497
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009498 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9499 {
9500 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9501 if($SymVer{$LibVersion}{$Alias}) {
9502 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9503 }
9504 }
9505
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009506 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009507 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009508 }
9509 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9510 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9511 }
9512 if($ExtendedCheck)
9513 { # --ext option
9514 addExtension($LibVersion);
9515 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009516
9517 # clean memory
9518 delete($SymbolInfo{$LibVersion});
9519
9520 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009521 { # detect allocable classes with public exported constructors
9522 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009523 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009524 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009525 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009526 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009527 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9528 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009529 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009530 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009531 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009532 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009533 $AllocableClass{$LibVersion}{$ClassName} = 1;
9534 }
9535 }
9536 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009537 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009538 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009539 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009540 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009541 if($CheckHeadersOnly)
9542 {
9543 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9544 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9545 { # all symbols except non-virtual inline
9546 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9547 }
9548 }
9549 else {
9550 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009551 }
9552 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009553 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009554 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009555 }
9556 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009557 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009558 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009559 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009560 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009561 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009562 if(defined $Base{"Type"}
9563 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009564 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009565 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009566 if($Name=~/<([^<>\s]+)>/)
9567 {
9568 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9569 $ReturnedClass{$LibVersion}{$Tid} = 1;
9570 }
9571 }
9572 else {
9573 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9574 }
9575 }
9576 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009577 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009578 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009579 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009580 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009581 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009582 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009583 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009584 if($Base{"Type"}=~/Struct|Class/)
9585 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009586 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009587 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9588 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009589 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009590 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009591 }
9592 }
9593 }
9594 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009595
9596 # mapping {short name => symbols}
9597 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009598 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009599 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009600 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009601 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009602 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009603 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009604 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009605 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9606 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009607 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009608 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009609 }
9610 }
9611 }
9612 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009613
9614 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009615 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009616 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009617 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009618 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009619 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9620 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009621 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009622 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009623 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009624 $ClassNames{$LibVersion}{$TName} = 1;
9625 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009626 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009627 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9628 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009629 }
9630 }
9631 }
9632 }
9633 }
9634}
9635
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009636sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009637{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009638 my ($Tid, $LibVersion) = @_;
9639 if(not $Tid) {
9640 return $Tid;
9641 }
9642
9643 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9644 {
9645 if($TName_Tid{$LibVersion}{$Name}) {
9646 return $TName_Tid{$LibVersion}{$Name};
9647 }
9648 }
9649
9650 return $Tid;
9651}
9652
9653sub register_SymbolUsage($$$)
9654{
9655 my ($InfoId, $UsedType, $LibVersion) = @_;
9656
9657 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9658 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9659 {
9660 register_TypeUsage($RTid, $UsedType, $LibVersion);
9661 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9662 }
9663 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9664 {
9665 register_TypeUsage($FCid, $UsedType, $LibVersion);
9666 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9667
9668 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9669 { # register "this" pointer
9670 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9671 }
9672 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9673 { # register "this" pointer (const method)
9674 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9675 }
9676 }
9677 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9678 {
9679 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9680 {
9681 register_TypeUsage($PTid, $UsedType, $LibVersion);
9682 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9683 }
9684 }
9685 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9686 {
9687 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9688 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9689 register_TypeUsage($TTid, $UsedType, $LibVersion);
9690 }
9691 }
9692}
9693
9694sub register_TypeUsage($$$)
9695{
9696 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009697 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009698 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009699 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009700 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009701 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009702 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009703 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009704
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009705 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009706 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009707 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009708 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009709 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009710 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9711 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9712 }
9713 }
9714
9715 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9716 {
9717 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009718 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009719 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009720 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9721 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009722 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009723 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9724 {
9725 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9726 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009727 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009728 }
9729 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009730 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009731 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009732 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009733 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9734 {
9735 register_TypeUsage($MTid, $UsedType, $LibVersion);
9736 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009737 }
9738 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009739 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009740 or $TInfo{"Type"} eq "MethodPtr"
9741 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009742 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009743 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009744 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009745 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009746 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009747 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009748 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9749 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009750 }
9751 }
9752 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009753 if($TInfo{"Type"} eq "FieldPtr")
9754 {
9755 if(my $RTid = $TInfo{"Return"}) {
9756 register_TypeUsage($RTid, $UsedType, $LibVersion);
9757 }
9758 if(my $CTid = $TInfo{"Class"}) {
9759 register_TypeUsage($CTid, $UsedType, $LibVersion);
9760 }
9761 }
9762 if($TInfo{"Type"} eq "MethodPtr")
9763 {
9764 if(my $CTid = $TInfo{"Class"}) {
9765 register_TypeUsage($CTid, $UsedType, $LibVersion);
9766 }
9767 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009768 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009769 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009770 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009771 $UsedType->{$TypeId} = 1;
9772 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9773 {
9774 register_TypeUsage($BTid, $UsedType, $LibVersion);
9775 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9776 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009777 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009778 else
9779 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9780 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009781 }
9782 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009783}
9784
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009785sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009786{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009787 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9788
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009789 if($Level eq "Dump")
9790 {
9791 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9792 { # TODO: check if this symbol is from
9793 # base classes of other target symbols
9794 return 1;
9795 }
9796 }
9797
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009798 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9799 { # stdc++ interfaces
9800 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009801 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009802
9803 my $Target = 0;
9804 if(my $Header = $SInfo->{"Header"}) {
9805 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9806 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009807 if($ExtendedCheck)
9808 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009809 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009810 $Target = 1;
9811 }
9812 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009813 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009814 {
9815 if($Target)
9816 {
9817 if($Level eq "Dump")
9818 { # dumped
9819 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009820 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009821 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009822 return 1;
9823 }
9824 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009825 else {
9826 return 1;
9827 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009828 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009829 elsif($Level eq "Source")
9830 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009831 return 1;
9832 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009833 elsif($Level eq "Binary")
9834 { # checked
9835 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9836 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9837 return 1;
9838 }
9839 }
9840 }
9841 }
9842 else
9843 { # library is available
9844 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9845 { # exported symbols
9846 return 1;
9847 }
9848 if($Level eq "Dump")
9849 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009850 if($BinaryOnly)
9851 {
9852 if($SInfo->{"Data"})
9853 {
9854 if($Target) {
9855 return 1;
9856 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009857 }
9858 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009859 else
9860 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009861 if($Target) {
9862 return 1;
9863 }
9864 }
9865 }
9866 elsif($Level eq "Source")
9867 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009868 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
9869 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009870 { # skip LOCAL symbols
9871 if($Target) {
9872 return 1;
9873 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009874 }
9875 }
9876 elsif($Level eq "Binary")
9877 { # checked
9878 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9879 {
9880 if($Target) {
9881 return 1;
9882 }
9883 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009884 }
9885 }
9886 return 0;
9887}
9888
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009889sub cleanDump($)
9890{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009891 my $LibVersion = $_[0];
9892 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9893 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009894 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9895 {
9896 delete($SymbolInfo{$LibVersion}{$InfoId});
9897 next;
9898 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009899 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009900 if(not $MnglName)
9901 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009902 delete($SymbolInfo{$LibVersion}{$InfoId});
9903 next;
9904 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009905 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009906 if(not $ShortName)
9907 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009908 delete($SymbolInfo{$LibVersion}{$InfoId});
9909 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009910 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009911 if($MnglName eq $ShortName)
9912 { # remove duplicate data
9913 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009914 }
9915 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9916 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9917 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009918 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9919 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9920 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009921 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009922 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009923 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009924 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009925 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9926 {
9927 delete($TypeInfo{$LibVersion}{$Tid});
9928 next;
9929 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009930 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009931 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009932 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009933 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9934 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9935 }
9936 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009937 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9938 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9939 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009940 }
9941}
9942
9943sub selectType($$)
9944{
9945 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009946
9947 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9948 {
9949 if(defined $TypeInfo{$LibVersion}{$Dupl})
9950 {
9951 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9952 { # duplicate
9953 return 0;
9954 }
9955 }
9956 }
9957
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009958 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9959 {
9960 if(not isBuiltIn($THeader))
9961 {
9962 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009963 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009964 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9965 {
9966 if(is_target_header($THeader, $LibVersion))
9967 { # from target headers
9968 if(not selfTypedef($Tid, $LibVersion)) {
9969 return 1;
9970 }
9971 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009972 }
9973 }
9974 }
9975 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009976 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009977}
9978
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009979sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009980{ # remove unused data types from the ABI dump
9981 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009982
9983 my %UsedType = ();
9984
9985 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009986 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009987 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009988 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009989 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009990 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009991 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009992 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009993 next;
9994 }
9995
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009996 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009997 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009998 if(selectType($Tid, $LibVersion))
9999 {
10000 my %Tree = ();
10001 register_TypeUsage($Tid, \%Tree, $LibVersion);
10002
10003 my $Tmpl = 0;
10004 foreach (sort {int($a)<=>int($b)} keys(%Tree))
10005 {
10006 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
10007 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
10008 {
10009 $Tmpl = 1;
10010 last;
10011 }
10012 }
10013 if(not $Tmpl)
10014 {
10015 foreach (keys(%Tree)) {
10016 $UsedType{$_} = 1;
10017 }
10018 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010019 }
10020 }
10021 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010022
10023 my %Delete = ();
10024
10025 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010026 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010027 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010028 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010029 next;
10030 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010031
10032 if($Kind eq "Extra")
10033 {
10034 my %Tree = ();
10035 register_TypeUsage($Tid, \%Tree, $LibVersion);
10036
10037 foreach (sort {int($a)<=>int($b)} keys(%Tree))
10038 {
10039 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
10040 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
10041 {
10042 $Delete{$Tid} = 1;
10043 last;
10044 }
10045 }
10046 }
10047 else
10048 {
10049 # remove type
10050 delete($TypeInfo{$LibVersion}{$Tid});
10051 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010052 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010053
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010054 if($Kind eq "Extra")
10055 { # remove duplicates
10056 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
10057 {
10058 if($UsedType{$Tid})
10059 { # All & Extended
10060 next;
10061 }
10062
10063 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10064
10065 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
10066 delete($TypeInfo{$LibVersion}{$Tid});
10067 }
10068 }
10069 }
10070
10071 foreach my $Tid (keys(%Delete))
10072 {
10073 delete($TypeInfo{$LibVersion}{$Tid});
10074 }
10075}
10076
10077sub check_Completeness($$)
10078{
10079 my ($Info, $LibVersion) = @_;
10080
10081 # data types
10082 if(defined $Info->{"Memb"})
10083 {
10084 foreach my $Pos (keys(%{$Info->{"Memb"}}))
10085 {
10086 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
10087 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
10088 }
10089 }
10090 }
10091 if(defined $Info->{"Base"})
10092 {
10093 foreach my $Bid (keys(%{$Info->{"Base"}})) {
10094 check_TypeInfo($Bid, $LibVersion);
10095 }
10096 }
10097 if(defined $Info->{"BaseType"}) {
10098 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
10099 }
10100 if(defined $Info->{"TParam"})
10101 {
10102 foreach my $Pos (keys(%{$Info->{"TParam"}}))
10103 {
10104 my $TName = $Info->{"TParam"}{$Pos}{"name"};
10105 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
10106 next;
10107 }
10108 if($TName eq "_BoolType") {
10109 next;
10110 }
10111 if($TName=~/\Asizeof\(/) {
10112 next;
10113 }
10114 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10115 check_TypeInfo($Tid, $LibVersion);
10116 }
10117 else
10118 {
10119 if(defined $Debug) {
10120 printMsg("WARNING", "missed type $TName");
10121 }
10122 }
10123 }
10124 }
10125
10126 # symbols
10127 if(defined $Info->{"Param"})
10128 {
10129 foreach my $Pos (keys(%{$Info->{"Param"}}))
10130 {
10131 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10132 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10133 }
10134 }
10135 }
10136 if(defined $Info->{"Return"}) {
10137 check_TypeInfo($Info->{"Return"}, $LibVersion);
10138 }
10139 if(defined $Info->{"Class"}) {
10140 check_TypeInfo($Info->{"Class"}, $LibVersion);
10141 }
10142}
10143
10144sub check_TypeInfo($$)
10145{
10146 my ($Tid, $LibVersion) = @_;
10147
10148 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10149 return;
10150 }
10151 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10152
10153 if(defined $TypeInfo{$LibVersion}{$Tid})
10154 {
10155 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10156 printMsg("ERROR", "missed type name ($Tid)");
10157 }
10158 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10159 }
10160 else {
10161 printMsg("ERROR", "missed type id $Tid");
10162 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010163}
10164
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010165sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010166{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010167 my ($TypeId, $LibVersion) = @_;
10168 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010169 if($Type{"Type"} eq "Typedef")
10170 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010171 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010172 if($Base{"Type"}=~/Class|Struct/)
10173 {
10174 if($Type{"Name"} eq $Base{"Name"}) {
10175 return 1;
10176 }
10177 elsif($Type{"Name"}=~/::(\w+)\Z/)
10178 {
10179 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10180 { # QPointer<QWidget>::QPointer
10181 return 1;
10182 }
10183 }
10184 }
10185 }
10186 return 0;
10187}
10188
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010189sub addExtension($)
10190{
10191 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010192 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010193 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010194 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010195 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010196 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10197 $TName=~s/\A(struct|union|class|enum) //;
10198 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010199
10200 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10201 "Header" => "extended.h",
10202 "ShortName" => $Symbol,
10203 "MnglName" => $Symbol,
10204 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10205 );
10206
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010207 $ExtendedSymbols{$Symbol} = 1;
10208 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10209 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010210 }
10211 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010212 $ExtendedSymbols{"external_func_0"} = 1;
10213 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10214 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010215}
10216
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010217sub findMethod($$$)
10218{
10219 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010220 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010221 {
10222 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10223 return $VirtMethodInClass;
10224 }
10225 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10226 return $VirtMethodInBaseClasses;
10227 }
10228 }
10229 return "";
10230}
10231
10232sub findMethod_Class($$$)
10233{
10234 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010235 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010236 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10237 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10238 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10239 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10240 { # search for interface with the same parameters suffix (overridden)
10241 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10242 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010243 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10244 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010245 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10246 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010247 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10248 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10249 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10250 return $Candidate;
10251 }
10252 }
10253 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010254 else
10255 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010256 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10257 return $Candidate;
10258 }
10259 }
10260 }
10261 }
10262 return "";
10263}
10264
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010265sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010266{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010267 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010268 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010269 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010270 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10271 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010272 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010273 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010274 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010275 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10276 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010277 { # pure virtual D2-destructors are marked as "virt" in the dump
10278 # virtual D2-destructors are NOT marked as "virt" in the dump
10279 # both destructors are not presented in the v-table
10280 next;
10281 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010282 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010283 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010285 }
10286}
10287
10288sub registerOverriding($)
10289{
10290 my $LibVersion = $_[0];
10291 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010292 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010293 foreach my $ClassName (@Classes)
10294 {
10295 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10296 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010297 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10298 { # pure virtuals
10299 next;
10300 }
10301 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10302 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010303 {
10304 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10305 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10306 { # both overridden virtual methods
10307 # and implemented pure virtual methods
10308 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10309 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10310 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10311 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010312 }
10313 }
10314 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10315 delete($VirtualTable{$LibVersion}{$ClassName});
10316 }
10317 }
10318}
10319
10320sub setVirtFuncPositions($)
10321{
10322 my $LibVersion = $_[0];
10323 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10324 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010325 my ($Num, $Rel) = (1, 0);
10326
10327 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010328 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010329 if($UsedDump{$LibVersion}{"DWARF"}) {
10330 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10331 }
10332 else {
10333 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10334 }
10335 foreach my $VirtFunc (@Funcs)
10336 {
10337 if($UsedDump{$LibVersion}{"DWARF"}) {
10338 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10339 }
10340 else {
10341 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10342 }
10343
10344 # set relative positions
10345 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10346 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10347 { # relative position excluding added and removed virtual functions
10348 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10349 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10350 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10351 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010352 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010353 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010354 }
10355 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010356 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010357 {
10358 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010359 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010360 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010361 }
10362 }
10363}
10364
10365sub get_sub_classes($$$)
10366{
10367 my ($ClassId, $LibVersion, $Recursive) = @_;
10368 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10369 my @Subs = ();
10370 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10371 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010372 if($Recursive)
10373 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010374 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10375 push(@Subs, $SubSubId);
10376 }
10377 }
10378 push(@Subs, $SubId);
10379 }
10380 return @Subs;
10381}
10382
10383sub get_base_classes($$$)
10384{
10385 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010386 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010387 return () if(not defined $ClassType{"Base"});
10388 my @Bases = ();
10389 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10390 keys(%{$ClassType{"Base"}}))
10391 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010392 if($Recursive)
10393 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010394 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10395 push(@Bases, $SubBaseId);
10396 }
10397 }
10398 push(@Bases, $BaseId);
10399 }
10400 return @Bases;
10401}
10402
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010403sub getVTable_Model($$)
10404{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010405 my ($ClassId, $LibVersion) = @_;
10406 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10407 my @Elements = ();
10408 foreach my $BaseId (@Bases, $ClassId)
10409 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010410 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010411 {
10412 if(defined $VirtualTable{$LibVersion}{$BName})
10413 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010414 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10415 if($UsedDump{$LibVersion}{"DWARF"}) {
10416 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10417 }
10418 else {
10419 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10420 }
10421 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010422 push(@Elements, $VFunc);
10423 }
10424 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010425 }
10426 }
10427 return @Elements;
10428}
10429
10430sub getVShift($$)
10431{
10432 my ($ClassId, $LibVersion) = @_;
10433 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10434 my $VShift = 0;
10435 foreach my $BaseId (@Bases)
10436 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010437 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010438 {
10439 if(defined $VirtualTable{$LibVersion}{$BName}) {
10440 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10441 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010442 }
10443 }
10444 return $VShift;
10445}
10446
10447sub getShift($$)
10448{
10449 my ($ClassId, $LibVersion) = @_;
10450 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10451 my $Shift = 0;
10452 foreach my $BaseId (@Bases)
10453 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010454 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010455 {
10456 if($Size!=1)
10457 { # not empty base class
10458 $Shift+=$Size;
10459 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010460 }
10461 }
10462 return $Shift;
10463}
10464
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010465sub getVTable_Size($$)
10466{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010467 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010468 my $Size = 0;
10469 # three approaches
10470 if(not $Size)
10471 { # real size
10472 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10473 $Size = keys(%VTable);
10474 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010475 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010476 if(not $Size)
10477 { # shared library symbol size
10478 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10479 $Size /= $WORD_SIZE{$LibVersion};
10480 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010481 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010482 if(not $Size)
10483 { # model size
10484 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10485 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10486 }
10487 }
10488 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010489}
10490
10491sub isCopyingClass($$)
10492{
10493 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010494 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010495}
10496
10497sub isLeafClass($$)
10498{
10499 my ($ClassId, $LibVersion) = @_;
10500 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10501}
10502
10503sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010504{ # check structured type for public fields
10505 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010506}
10507
10508sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010509{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010510 my ($TypePtr, $Skip, $Start, $End) = @_;
10511 return 0 if(not $TypePtr);
10512 if($End==-1) {
10513 $End = keys(%{$TypePtr->{"Memb"}})-1;
10514 }
10515 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10516 {
10517 if($Skip and $Skip->{$MemPos})
10518 { # skip removed/added fields
10519 next;
10520 }
10521 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10522 {
10523 if(isPublic($TypePtr, $MemPos)) {
10524 return ($MemPos+1);
10525 }
10526 }
10527 }
10528 return 0;
10529}
10530
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010531sub isReserved($)
10532{ # reserved fields == private
10533 my $MName = $_[0];
10534 if($MName=~/reserved|padding|f_spare/i) {
10535 return 1;
10536 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010537 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010538 return 1;
10539 }
10540 if($MName=~/(pad\d+)/i) {
10541 return 1;
10542 }
10543 return 0;
10544}
10545
10546sub isPublic($$)
10547{
10548 my ($TypePtr, $FieldPos) = @_;
10549 return 0 if(not $TypePtr);
10550 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10551 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10552 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10553 { # by name in C language
10554 # FIXME: add other methods to detect private members
10555 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10556 if($MName=~/priv|abidata|parent_object/i)
10557 { # C-styled private data
10558 return 0;
10559 }
10560 if(lc($MName) eq "abi")
10561 { # ABI information/reserved field
10562 return 0;
10563 }
10564 if(isReserved($MName))
10565 { # reserved fields
10566 return 0;
10567 }
10568 return 1;
10569 }
10570 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10571 { # by access in C++ language
10572 return 1;
10573 }
10574 return 0;
10575}
10576
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010577sub getVTable_Real($$)
10578{
10579 my ($ClassName, $LibVersion) = @_;
10580 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10581 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010582 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010583 if(defined $Type{"VTable"}) {
10584 return %{$Type{"VTable"}};
10585 }
10586 }
10587 return ();
10588}
10589
10590sub cmpVTables($)
10591{
10592 my $ClassName = $_[0];
10593 my $Res = cmpVTables_Real($ClassName, 1);
10594 if($Res==-1) {
10595 $Res = cmpVTables_Model($ClassName);
10596 }
10597 return $Res;
10598}
10599
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010600sub cmpVTables_Model($)
10601{
10602 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010603 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010604 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010605 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010606 return 1;
10607 }
10608 }
10609 return 0;
10610}
10611
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010612sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010613{
10614 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010615 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10616 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010617 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010618 my %VTable_Old = getVTable_Real($ClassName, 1);
10619 my %VTable_New = getVTable_Real($ClassName, 2);
10620 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010621 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010622 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010623 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010624 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010625 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10626 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010627 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010628 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010629 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010630 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010631 my $Entry1 = $VTable_Old{$Offset};
10632 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010633 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010634 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010635 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010636 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010637 $Entry1 = simpleVEntry($Entry1);
10638 $Entry2 = simpleVEntry($Entry2);
10639 if($Entry1 ne $Entry2)
10640 { # register as changed
10641 if($Entry1=~/::([^:]+)\Z/)
10642 {
10643 my $M1 = $1;
10644 if($Entry2=~/::([^:]+)\Z/)
10645 {
10646 my $M2 = $1;
10647 if($M1 eq $M2)
10648 { # overridden
10649 next;
10650 }
10651 }
10652 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010653 if(differentDumps("G"))
10654 {
10655 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10656 {
10657 # GCC 4.6.1: -0x00000000000000010
10658 # GCC 4.7.0: -16
10659 next;
10660 }
10661 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010662 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010663 }
10664 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010665 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010666}
10667
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010668sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010669{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010670 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010671 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10672 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010673 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010674 { # already registered
10675 next;
10676 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010677 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010678 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010679 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010680 foreach my $Symbol (@Affected)
10681 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010682 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010683 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010684 "Target"=>$ClassName);
10685 }
10686 }
10687 }
10688}
10689
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010690sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010691{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010692 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010693 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010694 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010695 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010696 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010697 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010698 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010699 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010700 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010701 if($TName_Tid{1}{$ClassName}
10702 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010703 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010704 if(defined $CompleteSignature{1}{$Symbol}
10705 and $CompleteSignature{1}{$Symbol}{"Virt"})
10706 { # override some method in v.1
10707 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010708 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010709 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010710 }
10711 }
10712 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010713 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010714 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010715 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010716 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010717 if($TName_Tid{2}{$ClassName}
10718 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010719 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010720 if(defined $CompleteSignature{2}{$Symbol}
10721 and $CompleteSignature{2}{$Symbol}{"Virt"})
10722 { # override some method in v.2
10723 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010724 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010725 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010726 }
10727 }
10728 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010729 if($Level eq "Binary")
10730 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010731 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010732 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10733 { # check replacements, including pure virtual methods
10734 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10735 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010736 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010737 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10738 if($AddedPos==$RemovedPos)
10739 {
10740 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10741 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10742 last; # other methods will be reported as "added" or "removed"
10743 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010744 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010745 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10746 {
10747 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10748 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010749 next;
10750 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010751 my $ProblemType = "Virtual_Replacement";
10752 my @Affected = ($RemovedVFunc);
10753 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10754 { # pure methods
10755 if(not isUsedClass($ClassId, 1, $Level))
10756 { # not a parameter of some exported method
10757 next;
10758 }
10759 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010760
10761 # affected all methods (both virtual and non-virtual ones)
10762 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10763 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010764 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010765 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010766 foreach my $AffectedInt (@Affected)
10767 {
10768 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10769 { # affected exported methods only
10770 next;
10771 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010772 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10773 next;
10774 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010775 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10776 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010777 "Target"=>get_Signature($AddedVFunc, 2),
10778 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10779 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010780 }
10781 }
10782 }
10783 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010784 if(not checkDump(1, "2.0")
10785 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010786 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010787 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010788 return;
10789 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010790 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010791 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010792 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010793 next if(not $ClassId_Old);
10794 if(not isCreatable($ClassId_Old, 1))
10795 { # skip classes without public constructors (including auto-generated)
10796 # example: class has only a private exported or private inline constructor
10797 next;
10798 }
10799 if($ClassName=~/>/)
10800 { # skip affected template instances
10801 next;
10802 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010803 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010804 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010805 if(not $ClassId_New) {
10806 next;
10807 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010808 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010809 if($Class_New{"Type"}!~/Class|Struct/)
10810 { # became typedef
10811 if($Level eq "Binary") {
10812 next;
10813 }
10814 if($Level eq "Source")
10815 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010816 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010817 if($Class_New{"Type"}!~/Class|Struct/) {
10818 next;
10819 }
10820 $ClassId_New = $Class_New{"Tid"};
10821 }
10822 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010823 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10824 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 +040010825
10826 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10827 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10828
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010829 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010830 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10831 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010832 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10833 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010834 my $Shift_Old = getShift($ClassId_Old, 1);
10835 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010836 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010837 my ($Added, $Removed) = (0, 0);
10838 my @StableBases_Old = ();
10839 foreach my $BaseId (@Bases_Old)
10840 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010841 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010842 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010843 push(@StableBases_Old, $BaseId);
10844 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010845 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010846 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010847 { # removed base
10848 # excluding namespace::SomeClass to SomeClass renaming
10849 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010850 if($Level eq "Binary")
10851 { # Binary-level
10852 if($Shift_Old ne $Shift_New)
10853 { # affected fields
10854 if(havePubFields(\%Class_Old)) {
10855 $ProblemKind .= "_And_Shift";
10856 }
10857 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10858 $ProblemKind .= "_And_Size";
10859 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010860 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010861 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10862 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010863 { # affected v-table
10864 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010865 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010866 }
10867 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010868 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010869 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10870 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010871 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10872 {
10873 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10874 if($ProblemKind=~/VTable/) {
10875 $VTableChanged_M{$SubName}=1;
10876 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010877 }
10878 }
10879 foreach my $Interface (@Affected)
10880 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010881 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10882 next;
10883 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010884 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010885 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010886 "Target"=>$BaseName,
10887 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10888 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10889 "Shift"=>abs($Shift_New-$Shift_Old) );
10890 }
10891 $Removed+=1;
10892 }
10893 }
10894 my @StableBases_New = ();
10895 foreach my $BaseId (@Bases_New)
10896 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010897 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010898 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010899 push(@StableBases_New, $BaseId);
10900 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010901 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010902 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010903 { # added base
10904 # excluding namespace::SomeClass to SomeClass renaming
10905 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010906 if($Level eq "Binary")
10907 { # Binary-level
10908 if($Shift_Old ne $Shift_New)
10909 { # affected fields
10910 if(havePubFields(\%Class_Old)) {
10911 $ProblemKind .= "_And_Shift";
10912 }
10913 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10914 $ProblemKind .= "_And_Size";
10915 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010916 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010917 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10918 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010919 { # affected v-table
10920 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010921 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010922 }
10923 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010924 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010925 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10926 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010927 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10928 {
10929 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10930 if($ProblemKind=~/VTable/) {
10931 $VTableChanged_M{$SubName}=1;
10932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010933 }
10934 }
10935 foreach my $Interface (@Affected)
10936 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010937 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10938 next;
10939 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010940 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010941 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010942 "Target"=>$BaseName,
10943 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10944 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10945 "Shift"=>abs($Shift_New-$Shift_Old) );
10946 }
10947 $Added+=1;
10948 }
10949 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010950 if($Level eq "Binary")
10951 { # Binary-level
10952 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010953 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10954 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010955 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010956 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010957 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010958 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010959 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010960 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10961 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010962 if($NewPos!=$OldPos)
10963 { # changed position of the base class
10964 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010965 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010966 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10967 next;
10968 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010969 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10970 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010971 "Target"=>$BaseName,
10972 "Old_Value"=>$OldPos-1,
10973 "New_Value"=>$NewPos-1 );
10974 }
10975 }
10976 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10977 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10978 { # became non-virtual base
10979 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10980 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010981 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10982 next;
10983 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010984 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10985 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010986 "Target"=>$BaseName );
10987 }
10988 }
10989 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10990 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10991 { # became virtual base
10992 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10993 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010994 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10995 next;
10996 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010997 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10998 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010999 "Target"=>$BaseName );
11000 }
11001 }
11002 }
11003 }
11004 # detect size changes in base classes
11005 if($Shift_Old!=$Shift_New)
11006 { # size of allocable class
11007 foreach my $BaseId (@StableBases_Old)
11008 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011009 my %BaseType = get_Type($BaseId, 1);
11010 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011011 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011012 if($Size_Old ne $Size_New
11013 and $Size_Old and $Size_New)
11014 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011015 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011016 if(isCopyingClass($BaseId, 1)) {
11017 $ProblemType = "Size_Of_Copying_Class";
11018 }
11019 elsif($AllocableClass{1}{$BaseType{"Name"}})
11020 {
11021 if($Size_New>$Size_Old)
11022 { # increased size
11023 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011024 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011025 else
11026 { # decreased size
11027 $ProblemType = "Size_Of_Allocable_Class_Decreased";
11028 if(not havePubFields(\%Class_Old))
11029 { # affected class has no public members
11030 next;
11031 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011032 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011033 }
11034 next if(not $ProblemType);
11035 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
11036 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011037 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
11038 next;
11039 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011040 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
11041 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011042 "Target"=>$BaseType{"Name"},
11043 "Old_Size"=>$Size_Old*$BYTE_SIZE,
11044 "New_Size"=>$Size_New*$BYTE_SIZE );
11045 }
11046 }
11047 }
11048 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011049 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011050 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011051 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011052 { # compare virtual tables size in base classes
11053 my $VShift_Old = getVShift($ClassId_Old, 1);
11054 my $VShift_New = getVShift($ClassId_New, 2);
11055 if($VShift_Old ne $VShift_New)
11056 { # changes in the base class or changes in the list of base classes
11057 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
11058 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
11059 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011060 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011061 foreach my $BaseId (@AllBases_Old)
11062 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011063 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011064 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011065 { # lost base
11066 next;
11067 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011068 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
11069 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011070 if($VSize_Old!=$VSize_New)
11071 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011072 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011073 { # TODO: affected non-virtual methods?
11074 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011075 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
11076 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011077 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011078 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011079 { # skip interfaces that have not changed the absolute virtual position
11080 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011081 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011082 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
11083 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011084 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011085 $VTableChanged_M{$BaseType{"Name"}} = 1;
11086 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011087 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11088 { # the reason of the layout change: added virtual functions
11089 next if($VirtualReplacement{$VirtFunc});
11090 my $ProblemType = "Added_Virtual_Method";
11091 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11092 $ProblemType = "Added_Pure_Virtual_Method";
11093 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011094 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011095 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011096 "Target"=>get_Signature($VirtFunc, 2) );
11097 }
11098 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11099 { # the reason of the layout change: removed virtual functions
11100 next if($VirtualReplacement{$VirtFunc});
11101 my $ProblemType = "Removed_Virtual_Method";
11102 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11103 $ProblemType = "Removed_Pure_Virtual_Method";
11104 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011105 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011106 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011107 "Target"=>get_Signature($VirtFunc, 1) );
11108 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011109 }
11110 }
11111 }
11112 }
11113 }
11114 }
11115 }
11116}
11117
11118sub isCreatable($$)
11119{
11120 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011121 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011122 or isCopyingClass($ClassId, $LibVersion)) {
11123 return 1;
11124 }
11125 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11126 { # Fix for incomplete data: if this class has
11127 # a base class then it should also has a constructor
11128 return 1;
11129 }
11130 if($ReturnedClass{$LibVersion}{$ClassId})
11131 { # returned by some method of this class
11132 # or any other class
11133 return 1;
11134 }
11135 return 0;
11136}
11137
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011138sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011139{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011140 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011141 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11142 { # parameter of some exported method
11143 return 1;
11144 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011145 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11146 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011147 { # method from target class
11148 return 1;
11149 }
11150 return 0;
11151}
11152
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011153sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011154{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011155 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011156 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011157 # - virtual
11158 # - pure-virtual
11159 # - non-virtual
11160 if($CompleteSignature{1}{$Interface}{"Data"})
11161 { # global data is not affected
11162 return;
11163 }
11164 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011165 if(not $Class_Id) {
11166 return;
11167 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011168 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011169 if(cmpVTables_Real($CName, 1)==0)
11170 { # no changes
11171 return;
11172 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011173 $CheckedTypes{$Level}{$CName} = 1;
11174 if($Level eq "Binary")
11175 { # Binary-level
11176 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11177 and not isUsedClass($Class_Id, 1, $Level))
11178 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011179 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011180 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011181 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011182 }
11183 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11184 {
11185 if(defined $VirtualTable{2}{$CName}{$Func}
11186 and defined $CompleteSignature{2}{$Func})
11187 {
11188 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11189 and $CompleteSignature{2}{$Func}{"PureVirt"})
11190 { # became pure virtual
11191 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11192 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011193 "Target"=>get_Signature_M($Func, 1) );
11194 $VTableChanged_M{$CName} = 1;
11195 }
11196 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11197 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11198 { # became non-pure virtual
11199 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11200 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011201 "Target"=>get_Signature_M($Func, 1) );
11202 $VTableChanged_M{$CName} = 1;
11203 }
11204 }
11205 }
11206 if($Level eq "Binary")
11207 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011208 # check virtual table structure
11209 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11210 {
11211 next if($Interface eq $AddedVFunc);
11212 next if($VirtualReplacement{$AddedVFunc});
11213 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11214 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11215 { # pure virtual methods affect all others (virtual and non-virtual)
11216 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011217 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011218 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011219 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011220 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011221 elsif(not defined $VirtualTable{1}{$CName}
11222 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011223 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011224 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011225 { # became polymorphous class, added v-table pointer
11226 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011227 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011228 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011229 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011230 }
11231 else
11232 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011233 my $VSize_Old = getVTable_Size($CName, 1);
11234 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011235 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011236 if(isCopyingClass($Class_Id, 1))
11237 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11238 my $ProblemType = "Added_Virtual_Method";
11239 if(isLeafClass($Class_Id, 1)) {
11240 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11241 }
11242 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11243 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011244 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011245 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011246 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011247 else
11248 {
11249 my $ProblemType = "Added_Virtual_Method";
11250 if(isLeafClass($Class_Id, 1)) {
11251 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11252 }
11253 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11254 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011255 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011256 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011257 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011258 }
11259 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011260 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11261 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011262 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011263 if(defined $VirtualTable{1}{$CName}
11264 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011265 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011266 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11267 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011268
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011269 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011270 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011271 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11272 foreach my $ASymbol (@Affected)
11273 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011274 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11275 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011276 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011277 next;
11278 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011279 }
11280 $CheckedSymbols{$Level}{$ASymbol} = 1;
11281 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11282 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011283 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011284 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011286 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011287 }
11288 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011289 else {
11290 # safe
11291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011292 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011293 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11294 {
11295 next if($VirtualReplacement{$RemovedVFunc});
11296 if($RemovedVFunc eq $Interface
11297 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11298 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011299 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011300 next;
11301 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011302 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011303 { # became non-polymorphous class, removed v-table pointer
11304 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11305 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011306 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011307 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011308 }
11309 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11310 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11311 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011312 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011313 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011314 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11315 next;
11316 }
11317 my $VPos_New = -1;
11318 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011319 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011320 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11321 }
11322 else
11323 {
11324 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011325 next;
11326 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011327 }
11328 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11329 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11330 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11331 {
11332 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11333 foreach my $ASymbol (@Affected)
11334 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011335 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11336 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011337 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011338 next;
11339 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011340 }
11341 my $ProblemType = "Removed_Virtual_Method";
11342 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11343 $ProblemType = "Removed_Pure_Virtual_Method";
11344 }
11345 $CheckedSymbols{$Level}{$ASymbol} = 1;
11346 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11347 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011348 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011349 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011350 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011351 }
11352 }
11353 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011354 }
11355 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011356 else
11357 { # Source-level
11358 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011359 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011360 next if($Interface eq $AddedVFunc);
11361 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011362 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011363 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11364 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011365 "Target"=>get_Signature($AddedVFunc, 2) );
11366 }
11367 }
11368 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11369 {
11370 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11371 {
11372 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11373 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011374 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011375 }
11376 }
11377 }
11378}
11379
11380sub find_MemberPair_Pos_byName($$)
11381{
11382 my ($Member_Name, $Pair_Type) = @_;
11383 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11384 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11385 {
11386 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11387 {
11388 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11389 $Name=~s/\A[_]+|[_]+\Z//g;
11390 if($Name eq $Member_Name) {
11391 return $MemberPair_Pos;
11392 }
11393 }
11394 }
11395 return "lost";
11396}
11397
11398sub find_MemberPair_Pos_byVal($$)
11399{
11400 my ($Member_Value, $Pair_Type) = @_;
11401 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11402 {
11403 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11404 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11405 return $MemberPair_Pos;
11406 }
11407 }
11408 return "lost";
11409}
11410
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011411sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011412{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011413 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011414 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011415 if( $_->{"T1"} eq $_[0]
11416 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011417 {
11418 return 1;
11419 }
11420 }
11421 return 0;
11422}
11423
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011424sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011425{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011426 my %IDs = (
11427 "T1" => $_[0],
11428 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011429 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011430 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011431}
11432
11433sub isRenamed($$$$$)
11434{
11435 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11436 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11437 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011438 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011439 if(not defined $Type2->{"Memb"}{$MemPos}) {
11440 return "";
11441 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011442 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011443 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011444
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011445 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11446 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011447 if($MemberPair_Pos_Rev eq "lost")
11448 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011449 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11450 { # base type match
11451 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011452 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011453 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11454 { # exact type match
11455 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011456 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011457 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11458 { # size match
11459 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011460 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011461 if(isReserved($Pair_Name))
11462 { # reserved fields
11463 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011464 }
11465 }
11466 return "";
11467}
11468
11469sub isLastElem($$)
11470{
11471 my ($Pos, $TypeRef) = @_;
11472 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11473 if($Name=~/last|count|max|total/i)
11474 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11475 return 1;
11476 }
11477 elsif($Name=~/END|NLIMITS\Z/)
11478 { # __RLIMIT_NLIMITS
11479 return 1;
11480 }
11481 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11482 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11483 { # NImageFormats, NColorRoles
11484 return 1;
11485 }
11486 return 0;
11487}
11488
11489sub nonComparable($$)
11490{
11491 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011492
11493 my $N1 = $T1->{"Name"};
11494 my $N2 = $T2->{"Name"};
11495
11496 $N1=~s/\A(struct|union|enum) //;
11497 $N2=~s/\A(struct|union|enum) //;
11498
11499 if($N1 ne $N2
11500 and not isAnon($N1)
11501 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011502 { # different names
11503 if($T1->{"Type"} ne "Pointer"
11504 or $T2->{"Type"} ne "Pointer")
11505 { # compare base types
11506 return 1;
11507 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011508 if($N1!~/\Avoid\s*\*/
11509 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011510 {
11511 return 1;
11512 }
11513 }
11514 elsif($T1->{"Type"} ne $T2->{"Type"})
11515 { # different types
11516 if($T1->{"Type"} eq "Class"
11517 and $T2->{"Type"} eq "Struct")
11518 { # "class" to "struct"
11519 return 0;
11520 }
11521 elsif($T2->{"Type"} eq "Class"
11522 and $T1->{"Type"} eq "Struct")
11523 { # "struct" to "class"
11524 return 0;
11525 }
11526 else
11527 { # "class" to "enum"
11528 # "union" to "class"
11529 # ...
11530 return 1;
11531 }
11532 }
11533 return 0;
11534}
11535
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011536sub isOpaque($)
11537{
11538 my $T = $_[0];
11539 if(not defined $T->{"Memb"})
11540 {
11541 return 1;
11542 }
11543 return 0;
11544}
11545
11546sub removeVPtr($)
11547{ # support for old ABI dumps
11548 my $TPtr = $_[0];
11549 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11550 if($#Pos>=1)
11551 {
11552 foreach my $Pos (0 .. $#Pos-1)
11553 {
11554 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11555 }
11556 delete($TPtr->{"Memb"}{$#Pos});
11557 }
11558}
11559
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011560sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011561{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011562 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011563 return {} if(not $Type1_Id or not $Type2_Id);
11564
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011565 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011566 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011567 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011568 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011569
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011570 my %Type1 = get_Type($Type1_Id, 1);
11571 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011572 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011573 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011574 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011575
11576 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011577 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11578 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011579
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011580 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11581
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011582 my %SubProblems = ();
11583
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011584 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11585 {
11586 if($Type1_Pure{"Type"}=~/Struct|Union/
11587 and $Type2_Pure{"Type"}=~/Struct|Union/)
11588 {
11589 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11590 {
11591 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11592 "Target"=>$Type1_Pure{"Name"},
11593 "Type_Name"=>$Type1_Pure{"Name"} );
11594
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011595 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011596 }
11597 }
11598 }
11599
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011600 if(not $Type1_Pure{"Size"}
11601 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011602 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011603 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11604 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11605 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011606 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011607 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011608 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011609 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011610 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011611 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011612 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011613 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11614 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11615 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011616
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011617 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11618 { # support for old ABI dumps
11619 # _vptr field added in 3.0
11620 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11621 {
11622 if(defined $Type2_Pure{"Memb"}
11623 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11624 {
11625 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11626 delete($Type2_Pure{"Memb"}{0});
11627 }
11628 else {
11629 removeVPtr(\%Type2_Pure);
11630 }
11631 }
11632 }
11633 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11634 {
11635 if(defined $Type1_Pure{"Memb"}
11636 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11637 {
11638 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11639 delete($Type1_Pure{"Memb"}{0});
11640 }
11641 else {
11642 removeVPtr(\%Type1_Pure);
11643 }
11644 }
11645 }
11646 }
11647
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011648 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11649 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011650
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011651 if(not $UseOldDumps and %Typedef_1 and %Typedef_2
11652 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11653 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011654 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011655 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11656 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011657 if($Base_1{"Name"} ne $Base_2{"Name"})
11658 {
11659 if(differentDumps("G")
11660 or differentDumps("V"))
11661 { # different GCC versions or different dumps
11662 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11663 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11664 # std::__va_list and __va_list
11665 $Base_1{"Name"}=~s/\A(\w+::)+//;
11666 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011667 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11668 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011669 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011670 }
11671 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11672 and $Base_1{"Name"} ne $Base_2{"Name"})
11673 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011674 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011675 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011676 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011677 {
11678 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11679 "Target"=>$Typedef_1{"Name"},
11680 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011681 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11682 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11683 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011684 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11685 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011686 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011687 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011688 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11689 {
11690 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11691 "Target"=>$Typedef_1{"Name"},
11692 "Type_Name"=>$Typedef_1{"Name"},
11693 "Old_Value"=>$Base_1{"Name"},
11694 "New_Value"=>$Base_2{"Name"} );
11695 }
11696 else
11697 {
11698 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11699 "Target"=>$Typedef_1{"Name"},
11700 "Type_Name"=>$Typedef_1{"Name"},
11701 "Old_Value"=>$Base_1{"Name"},
11702 "New_Value"=>$Base_2{"Name"} );
11703 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011704 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011705 }
11706 }
11707 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11708 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011709 my $TT1 = $Type1_Pure{"Type"};
11710 my $TT2 = $Type2_Pure{"Type"};
11711
11712 if($TT1 ne $TT2
11713 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011714 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011715 my $Short1 = $Type1_Pure{"Name"};
11716 my $Short2 = $Type2_Pure{"Name"};
11717
11718 $Short1=~s/\A\Q$TT1\E //ig;
11719 $Short2=~s/\A\Q$TT2\E //ig;
11720
11721 if($Short1 eq $Short2)
11722 {
11723 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11724 "Target"=>$Type1_Pure{"Name"},
11725 "Type_Name"=>$Type1_Pure{"Name"},
11726 "Old_Value"=>lc($Type1_Pure{"Type"}),
11727 "New_Value"=>lc($Type2_Pure{"Type"}) );
11728 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011729 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011730 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011731 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011732 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011733 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11734 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11735 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11736 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011737 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011738 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011739 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011740 {
11741 my $ProblemKind = "DataType_Size";
11742 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011743 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011744 {
11745 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11746 $ProblemKind = "Size_Of_Copying_Class";
11747 }
11748 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11749 {
11750 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11751 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11752 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011753 else
11754 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011755 # descreased size of allocable class
11756 # it has no special effects
11757 }
11758 }
11759 }
11760 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11761 "Target"=>$Type1_Pure{"Name"},
11762 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011763 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011764 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011765 }
11766 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011767 if(defined $Type1_Pure{"BaseType"}
11768 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011769 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011770 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11771 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011772 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011773 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11774 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011775 }
11776 }
11777 }
11778 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11779 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11780 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11781 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11782 { # detect removed and renamed fields
11783 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11784 next if(not $Member_Name);
11785 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);
11786 if($MemberPair_Pos eq "lost")
11787 {
11788 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11789 {
11790 if(isUnnamed($Member_Name))
11791 { # support for old-version dumps
11792 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011793 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011794 next;
11795 }
11796 }
11797 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11798 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011799 $RenamedField{$Member_Pos} = $RenamedTo;
11800 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011801 }
11802 else
11803 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011804 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011805 }
11806 }
11807 elsif($Type1_Pure{"Type"} eq "Enum")
11808 {
11809 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11810 next if($Member_Value1 eq "");
11811 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11812 if($MemberPair_Pos ne "lost")
11813 { # renamed
11814 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11815 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11816 if($MemberPair_Pos_Rev eq "lost")
11817 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011818 $RenamedField{$Member_Pos} = $RenamedTo;
11819 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011820 }
11821 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011822 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011823 }
11824 }
11825 else
11826 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011827 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011828 }
11829 }
11830 }
11831 else
11832 { # related
11833 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11834 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11835 }
11836 }
11837 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11838 { # detect added fields
11839 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11840 next if(not $Member_Name);
11841 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);
11842 if($MemberPair_Pos eq "lost")
11843 {
11844 if(isUnnamed($Member_Name))
11845 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011846 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011847 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011848 next;
11849 }
11850 }
11851 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11852 {
11853 if(not $RenamedField_Rev{$Member_Pos})
11854 { # added
11855 $AddedField{$Member_Pos}=1;
11856 }
11857 }
11858 }
11859 }
11860 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11861 { # detect moved fields
11862 my (%RelPos, %RelPosName, %AbsPos) = ();
11863 my $Pos = 0;
11864 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11865 { # relative positions in 1st version
11866 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11867 next if(not $Member_Name);
11868 if(not $RemovedField{$Member_Pos})
11869 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011870 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011871 $RelPosName{1}{$Pos} = $Member_Name;
11872 $AbsPos{1}{$Pos++} = $Member_Pos;
11873 }
11874 }
11875 $Pos = 0;
11876 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11877 { # relative positions in 2nd version
11878 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11879 next if(not $Member_Name);
11880 if(not $AddedField{$Member_Pos})
11881 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011882 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011883 $RelPosName{2}{$Pos} = $Member_Name;
11884 $AbsPos{2}{$Pos++} = $Member_Pos;
11885 }
11886 }
11887 foreach my $Member_Name (keys(%{$RelPos{1}}))
11888 {
11889 my $RPos1 = $RelPos{1}{$Member_Name};
11890 my $AbsPos1 = $NameToPosA{$Member_Name};
11891 my $Member_Name2 = $Member_Name;
11892 if(my $RenamedTo = $RenamedField{$AbsPos1})
11893 { # renamed
11894 $Member_Name2 = $RenamedTo;
11895 }
11896 my $RPos2 = $RelPos{2}{$Member_Name2};
11897 if($RPos2 ne "" and $RPos1 ne $RPos2)
11898 { # different relative positions
11899 my $AbsPos2 = $NameToPosB{$Member_Name2};
11900 if($AbsPos1 ne $AbsPos2)
11901 { # different absolute positions
11902 my $ProblemType = "Moved_Field";
11903 if(not isPublic(\%Type1_Pure, $AbsPos1))
11904 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011905 if($Level eq "Source") {
11906 next;
11907 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011908 $ProblemType = "Moved_Private_Field";
11909 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011910 if($Level eq "Binary"
11911 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011912 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011913 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011914 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011915 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011916 if($MemSize1 ne $MemSize2) {
11917 $ProblemType .= "_And_Size";
11918 }
11919 }
11920 if($ProblemType eq "Moved_Private_Field") {
11921 next;
11922 }
11923 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11924 "Target"=>$Member_Name,
11925 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011926 "Old_Value"=>$RPos1,
11927 "New_Value"=>$RPos2 );
11928 }
11929 }
11930 }
11931 }
11932 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011933 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011934 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11935 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011936 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011937 if(my $RenamedTo = $RenamedField{$Member_Pos})
11938 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011939 if(defined $Constants{2}{$Member_Name})
11940 {
11941 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11942 { # define OLD NEW
11943 next; # Safe
11944 }
11945 }
11946
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011947 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11948 {
11949 if(isPublic(\%Type1_Pure, $Member_Pos))
11950 {
11951 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11952 "Target"=>$Member_Name,
11953 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011954 "Old_Value"=>$Member_Name,
11955 "New_Value"=>$RenamedTo );
11956 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011957 elsif(isReserved($Member_Name))
11958 {
11959 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11960 "Target"=>$Member_Name,
11961 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011962 "Old_Value"=>$Member_Name,
11963 "New_Value"=>$RenamedTo );
11964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011965 }
11966 elsif($Type1_Pure{"Type"} eq "Enum")
11967 {
11968 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11969 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11970 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011971 "Old_Value"=>$Member_Name,
11972 "New_Value"=>$RenamedTo );
11973 }
11974 }
11975 elsif($RemovedField{$Member_Pos})
11976 { # removed
11977 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11978 {
11979 my $ProblemType = "Removed_Field";
11980 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011981 or isUnnamed($Member_Name))
11982 {
11983 if($Level eq "Source") {
11984 next;
11985 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011986 $ProblemType = "Removed_Private_Field";
11987 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011988 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011989 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011990 {
11991 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11992 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011993 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 +040011994 { # changed offset
11995 $ProblemType .= "_And_Layout";
11996 }
11997 }
11998 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11999 { # affected size
12000 $ProblemType .= "_And_Size";
12001 }
12002 }
12003 if($ProblemType eq "Removed_Private_Field") {
12004 next;
12005 }
12006 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12007 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012008 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012009 }
12010 elsif($Type2_Pure{"Type"} eq "Union")
12011 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012012 if($Level eq "Binary"
12013 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012014 {
12015 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
12016 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012017 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012018 }
12019 else
12020 {
12021 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
12022 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012023 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012024 }
12025 }
12026 elsif($Type1_Pure{"Type"} eq "Enum")
12027 {
12028 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
12029 "Target"=>$Member_Name,
12030 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012031 "Old_Value"=>$Member_Name );
12032 }
12033 }
12034 else
12035 { # changed
12036 my $MemberPair_Pos = $RelatedField{$Member_Pos};
12037 if($Type1_Pure{"Type"} eq "Enum")
12038 {
12039 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12040 next if($Member_Value1 eq "");
12041 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12042 next if($Member_Value2 eq "");
12043 if($Member_Value1 ne $Member_Value2)
12044 {
12045 my $ProblemType = "Enum_Member_Value";
12046 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12047 $ProblemType = "Enum_Last_Member_Value";
12048 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012049 if($SkipConstants{1}{$Member_Name}) {
12050 $ProblemType = "Enum_Private_Member_Value";
12051 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012052 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12053 "Target"=>$Member_Name,
12054 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012055 "Old_Value"=>$Member_Value1,
12056 "New_Value"=>$Member_Value2 );
12057 }
12058 }
12059 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12060 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012061 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12062 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12063
12064 if($Access1 ne "private"
12065 and $Access2 eq "private")
12066 {
12067 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12068 "Target"=>$Member_Name,
12069 "Type_Name"=>$Type1_Pure{"Name"});
12070 }
12071 elsif($Access1 ne "protected"
12072 and $Access1 ne "private"
12073 and $Access2 eq "protected")
12074 {
12075 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12076 "Target"=>$Member_Name,
12077 "Type_Name"=>$Type1_Pure{"Name"});
12078 }
12079
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012080 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12081 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012082 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012083 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12084 $SizeV1 = $BSize1;
12085 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012086 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012087 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12088 $SizeV2 = $BSize2;
12089 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012090 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12091 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012092 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012093 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012094 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012095 {
12096 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12097 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12098 { # field size change (including anon-structures and unions)
12099 # - same types
12100 # - unnamed types
12101 # - bitfields
12102 my $ProblemType = "Field_Size";
12103 if(not isPublic(\%Type1_Pure, $Member_Pos)
12104 or isUnnamed($Member_Name))
12105 { # should not be accessed by applications, goes to "Low Severity"
12106 # example: "abidata" members in GStreamer types
12107 $ProblemType = "Private_".$ProblemType;
12108 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012109 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 +040012110 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012111 if($Type2_Pure{"Type"} ne "Union"
12112 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012113 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012114 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 +040012115 { # changed offset
12116 $ProblemType .= "_And_Layout";
12117 }
12118 }
12119 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12120 $ProblemType .= "_And_Type_Size";
12121 }
12122 }
12123 if($ProblemType eq "Private_Field_Size")
12124 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012125 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012126 if($ProblemType eq "Field_Size")
12127 {
12128 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12129 { # Low severity
12130 $ProblemType = "Struct_Field_Size_Increased";
12131 }
12132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012133 if($ProblemType)
12134 { # register a problem
12135 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12136 "Target"=>$Member_Name,
12137 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012138 "Old_Size"=>$SizeV1,
12139 "New_Size"=>$SizeV2);
12140 }
12141 }
12142 }
12143 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12144 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12145 { # do NOT check bitfield type changes
12146 next;
12147 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012148 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012149 {
12150 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12151 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12152 {
12153 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12154 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012155 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012156 }
12157 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12158 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12159 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012160 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012161 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012162 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012163 }
12164 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012165 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12166 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012167 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012168 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12169 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012170
12171 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012172 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012173 or $ProblemType eq "Field_Type_And_Size"
12174 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012175 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012176 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012177 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012178 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012179 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012180 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012181 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012182 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012183 }
12184 }
12185 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12186 {
12187 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012188 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012189 }
12190 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012191 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012192 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012193 }
12194 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12195 {
12196 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012197 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012198 }
12199 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012200 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012201 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012202 }
12203 }
12204 }
12205
12206 if($Level eq "Source")
12207 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012208 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012209 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012210 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12211 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012212
12213 if($ProblemType eq "Field_Type")
12214 {
12215 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012216 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012217 }
12218 }
12219 }
12220 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012221
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012222 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012223 {
12224 my $ProblemType_Init = $ProblemType;
12225 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012226 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012227 if(not isPublic(\%Type1_Pure, $Member_Pos)
12228 or isUnnamed($Member_Name)) {
12229 $ProblemType = "Private_".$ProblemType;
12230 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012231 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 +040012232 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012233 if($Type2_Pure{"Type"} ne "Union"
12234 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012235 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012236 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 +040012237 { # changed offset
12238 $ProblemType .= "_And_Layout";
12239 }
12240 }
12241 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12242 $ProblemType .= "_And_Type_Size";
12243 }
12244 }
12245 }
12246 else
12247 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012248 # TODO: Private_Field_Type rule?
12249
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012250 if(not isPublic(\%Type1_Pure, $Member_Pos)
12251 or isUnnamed($Member_Name)) {
12252 next;
12253 }
12254 }
12255 if($ProblemType eq "Private_Field_Type_And_Size")
12256 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012257 }
12258 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12259 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012260 "Type_Name"=>$Type1_Pure{"Name"});
12261
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012262 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012263 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012264 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012265 }
12266 }
12267 if(not isPublic(\%Type1_Pure, $Member_Pos))
12268 { # do NOT check internal type changes
12269 next;
12270 }
12271 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012272 { # checking member type changes
12273 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12274
12275 my %DupProblems = ();
12276
12277 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012278 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012279 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012280 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012281 if(not defined $AllAffected)
12282 {
12283 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12284 next;
12285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012286 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012287
12288 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12289 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12290
12291 if(not defined $AllAffected)
12292 {
12293 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012294 }
12295 }
12296 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012297
12298 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012299 }
12300 }
12301 }
12302 }
12303 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12304 { # checking added members, public and private
12305 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12306 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012307 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012308 if($AddedField{$Member_Pos})
12309 { # added
12310 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12311 {
12312 my $ProblemType = "Added_Field";
12313 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012314 or isUnnamed($Member_Name))
12315 {
12316 if($Level eq "Source") {
12317 next;
12318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012319 $ProblemType = "Added_Private_Field";
12320 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012321 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012322 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012323 {
12324 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12325 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012326 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 +040012327 { # changed offset
12328 $ProblemType .= "_And_Layout";
12329 }
12330 }
12331 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12332 $ProblemType .= "_And_Size";
12333 }
12334 }
12335 if($ProblemType eq "Added_Private_Field")
12336 { # skip added private fields
12337 next;
12338 }
12339 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12340 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012341 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012342 }
12343 elsif($Type2_Pure{"Type"} eq "Union")
12344 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012345 if($Level eq "Binary"
12346 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012347 {
12348 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12349 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012350 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012351 }
12352 else
12353 {
12354 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12355 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012356 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012357 }
12358 }
12359 elsif($Type2_Pure{"Type"} eq "Enum")
12360 {
12361 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12362 next if($Member_Value eq "");
12363 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12364 "Target"=>$Member_Name,
12365 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012366 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012367 }
12368 }
12369 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012370
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012371 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012372 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012373}
12374
12375sub isUnnamed($) {
12376 return $_[0]=~/\Aunnamed\d+\Z/;
12377}
12378
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012379sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012380{
12381 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012382 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12383 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12384 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12385 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012386 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012387 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012388 }
12389 return $TypeName;
12390}
12391
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012392sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012393{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012394 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012395 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012396 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12397 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012398 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012399 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12400 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012401 return () if(not $Type{"Type"});
12402 if($Type{"Type"} ne $Type_Type)
12403 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012404 return () if(not $Type{"BaseType"});
12405 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012406 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012407 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012408 return %Type;
12409}
12410
12411my %TypeSpecAttributes = (
12412 "Const" => 1,
12413 "Volatile" => 1,
12414 "ConstVolatile" => 1,
12415 "Restrict" => 1,
12416 "Typedef" => 1
12417);
12418
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012419sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012420{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012421 my ($TypeId, $Info) = @_;
12422 if(not $TypeId or not $Info
12423 or not $Info->{$TypeId}) {
12424 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012425 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012426 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12427 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12428 }
12429 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012430 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012431 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012432 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012433 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012434 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012435 return %Type;
12436}
12437
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012438sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012439{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012440 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012441 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012442 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12443 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012444 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012445 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12446 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012447 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12448 my $PLevel = 0;
12449 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12450 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012451 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012452 return $PLevel if(not $Type{"BaseType"});
12453 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12454 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12455 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012456}
12457
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012458sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012459{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012460 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012461 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012462 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12463 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012464 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012465 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12466 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012467 return %Type if(not $Type{"BaseType"});
12468 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012469 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012470 return %Type;
12471}
12472
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012473sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012474{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012475 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012476 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012477 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12478 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012479 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012480 my $Qual = "";
12481 if($Type{"Type"} eq "Pointer") {
12482 $Qual .= "*";
12483 }
12484 elsif($Type{"Type"} eq "Ref") {
12485 $Qual .= "&";
12486 }
12487 elsif($Type{"Type"} eq "ConstVolatile") {
12488 $Qual .= "const volatile";
12489 }
12490 elsif($Type{"Type"} eq "Const"
12491 or $Type{"Type"} eq "Volatile"
12492 or $Type{"Type"} eq "Restrict") {
12493 $Qual .= lc($Type{"Type"});
12494 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012495 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012496 return $BQual.$Qual;
12497}
12498
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012499sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012500{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012501 my ($TypeId, $Info) = @_;
12502 if(not $TypeId or not $Info
12503 or not $Info->{$TypeId}) {
12504 return ();
12505 }
12506 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012507 return %Type if(not $Type{"BaseType"});
12508 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012509 {
12510 if($Info->{$BTid}) {
12511 return %{$Info->{$BTid}};
12512 }
12513 else { # something is going wrong
12514 return ();
12515 }
12516 }
12517 else {
12518 return %Type;
12519 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012520}
12521
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012522sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012523{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012524 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012525 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012526 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12527 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012528}
12529
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012530sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012531{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012532 my $Symbol = $_[0];
12533 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12534}
12535
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012536sub isInLineInst($$$) {
12537 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12538}
12539
12540sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012541{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012542 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012543 if($CheckObjectsOnly)
12544 {
12545 if($Symbol!~/\A(_Z|\?)/) {
12546 return 0;
12547 }
12548 if(my $Signature = $tr_name{$Symbol})
12549 {
12550 if(index($Signature,">")==-1) {
12551 return 0;
12552 }
12553 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
12554 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012555 if(index($ShortName,"<")!=-1
12556 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012557 return 1;
12558 }
12559 }
12560 }
12561 }
12562 else
12563 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012564 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012565 {
12566 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
12567 {
12568 if(index($ClassName,"<")!=-1) {
12569 return 1;
12570 }
12571 }
12572 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012573 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012574 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012575 if(index($ShortName,"<")!=-1
12576 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012577 return 1;
12578 }
12579 }
12580 }
12581 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012582}
12583
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012584sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012585{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012586 my ($Symbol, $SInfo, $LibVersion) = @_;
12587 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012588 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012589 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012590 { # class specialization
12591 return 1;
12592 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012593 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012594 { # method specialization
12595 return 1;
12596 }
12597 }
12598 return 0;
12599}
12600
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012601sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012602{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012603 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012604 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012605 { # non-public global data
12606 return 0;
12607 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012608
12609 if(defined $SkipInternal)
12610 {
12611 return 0 if($Symbol=~/($SkipInternal)/);
12612 }
12613
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012614 if($CheckObjectsOnly) {
12615 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
12616 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012617 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012618 { # support for old ABI dumps in --headers-only mode
12619 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12620 {
12621 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12622 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012623 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012624 if(not $PType or $PType eq "Unknown") {
12625 return 0;
12626 }
12627 }
12628 }
12629 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012630 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012631 {
12632 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012633 if($SkipSymbols{$LibVersion}{$Symbol})
12634 { # user defined symbols to ignore
12635 return 0;
12636 }
12637 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12638 if(not $NameSpace and $ClassId)
12639 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012640 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012641 }
12642 if($NameSpace)
12643 { # user defined namespaces to ignore
12644 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12645 return 0;
12646 }
12647 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12648 { # nested namespaces
12649 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12650 return 0;
12651 }
12652 }
12653 }
12654 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
12655 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012656 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012657 { # --skip-headers or <skip_headers> (not <skip_including>)
12658 if($Skip==1) {
12659 return 0;
12660 }
12661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012662 }
12663 if($SymbolsListPath and not $SymbolsList{$Symbol})
12664 { # user defined symbols
12665 return 0;
12666 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012667 if($SkipSymbolsListPath and $SkipSymbolsList{$Symbol})
12668 { # user defined symbols
12669 return 0;
12670 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012671 if($AppPath and not $SymbolsList_App{$Symbol})
12672 { # user defined symbols (in application)
12673 return 0;
12674 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012675 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12676 { # non-target symbols
12677 return 0;
12678 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012679 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012680 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012681 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012682 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012683 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012684 return 0;
12685 }
12686 }
12687 else
12688 {
12689 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012690 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012691 {
12692 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12693 { # inline virtual methods
12694 if($Type=~/InlineVirt/) {
12695 return 1;
12696 }
12697 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12698 if(not $Allocable)
12699 { # check bases
12700 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12701 {
12702 if(not isCopyingClass($DCId, $LibVersion))
12703 { # exists a derived class without default c-tor
12704 $Allocable=1;
12705 last;
12706 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012708 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012709 if(not $Allocable) {
12710 return 0;
12711 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012712 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012713 else
12714 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012715 return 0;
12716 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012717 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012718 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012719 }
12720 }
12721 return 1;
12722}
12723
12724sub mergeImpl()
12725{
12726 my $DiffCmd = get_CmdPath("diff");
12727 if(not $DiffCmd) {
12728 exitStatus("Not_Found", "can't find \"diff\"");
12729 }
12730 foreach my $Interface (sort keys(%{$Symbol_Library{1}}))
12731 { # implementation changes
12732 next if($CompleteSignature{1}{$Interface}{"Private"});
12733 next if(not $CompleteSignature{1}{$Interface}{"Header"} and not $CheckObjectsOnly);
12734 next if(not $Symbol_Library{2}{$Interface} and not $Symbol_Library{2}{$SymVer{2}{$Interface}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012735 if(not symbolFilter($Interface, 1, "Affected", "Binary")) {
12736 next;
12737 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012738 my $Impl1 = canonifyImpl($Interface_Impl{1}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012739 next if(not $Impl1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012740 my $Impl2 = canonifyImpl($Interface_Impl{2}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012741 next if(not $Impl2);
12742 if($Impl1 ne $Impl2)
12743 {
12744 writeFile("$TMP_DIR/impl1", $Impl1);
12745 writeFile("$TMP_DIR/impl2", $Impl2);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012746 my $Diff = `$DiffCmd -rNau \"$TMP_DIR/impl1\" \"$TMP_DIR/impl2\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012747 $Diff=~s/(---|\+\+\+).+\n//g;
12748 $Diff=~s/[ ]{3,}/ /g;
12749 $Diff=~s/\n\@\@/\n \n\@\@/g;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012750 unlink("$TMP_DIR/impl1");
12751 unlink("$TMP_DIR/impl2");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040012752 %{$CompatProblems_Impl{$Interface}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012753 "Diff" => get_CodeView($Diff) );
12754 }
12755 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012756
12757 # clean memory
12758 %Interface_Impl = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012759}
12760
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012761sub canonifyImpl($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012762{
12763 my $FuncBody= $_[0];
12764 return "" if(not $FuncBody);
12765 $FuncBody=~s/0x[a-f\d]+/0x?/g;# addr
12766 $FuncBody=~s/((\A|\n)[a-z]+[\t ]+)[a-f\d]+([^x]|\Z)/$1?$3/g;# call, jump
12767 $FuncBody=~s/# [a-f\d]+ /# ? /g;# call, jump
12768 $FuncBody=~s/%([a-z]+[a-f\d]*)/\%reg/g;# registers
12769 while($FuncBody=~s/\nnop[ \t]*(\n|\Z)/$1/g){};# empty op
12770 $FuncBody=~s/<.+?\.cpp.+?>/<name.cpp>/g;
12771 $FuncBody=~s/(\A|\n)[a-f\d]+ </$1? </g;# 5e74 <_ZN...
12772 $FuncBody=~s/\.L\d+/.L/g;
12773 $FuncBody=~s/#(-?)\d+/#$1?/g;# r3, [r3, #120]
12774 $FuncBody=~s/[\n]{2,}/\n/g;
12775 return $FuncBody;
12776}
12777
12778sub get_CodeView($)
12779{
12780 my $Code = $_[0];
12781 my $View = "";
12782 foreach my $Line (split(/\n/, $Code))
12783 {
12784 if($Line=~s/\A(\+|-)/$1 /g)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012785 { # bold line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012786 $View .= "<tr><td><b>".htmlSpecChars($Line)."</b></td></tr>\n";
12787 }
12788 else {
12789 $View .= "<tr><td>".htmlSpecChars($Line)."</td></tr>\n";
12790 }
12791 }
12792 return "<table class='code_view'>$View</table>\n";
12793}
12794
12795sub getImplementations($$)
12796{
12797 my ($LibVersion, $Path) = @_;
12798 return if(not $LibVersion or not -e $Path);
12799 if($OSgroup eq "macos")
12800 {
12801 my $OtoolCmd = get_CmdPath("otool");
12802 if(not $OtoolCmd) {
12803 exitStatus("Not_Found", "can't find \"otool\"");
12804 }
12805 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012806 foreach my $Line (split(/\n/, `$OtoolCmd -tv \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012807 {
12808 if($Line=~/\A\s*_(\w+)\s*:/i) {
12809 $CurInterface = $1;
12810 }
12811 elsif($Line=~/\A\s*[\da-z]+\s+(.+?)\Z/i) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012812 $Interface_Impl{$LibVersion}{$CurInterface} .= $1."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012813 }
12814 }
12815 }
12816 else
12817 {
12818 my $ObjdumpCmd = get_CmdPath("objdump");
12819 if(not $ObjdumpCmd) {
12820 exitStatus("Not_Found", "can't find \"objdump\"");
12821 }
12822 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012823 foreach my $Line (split(/\n/, `$ObjdumpCmd -d \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012824 {
12825 if($Line=~/\A[\da-z]+\s+<(\w+)>/i) {
12826 $CurInterface = $1;
12827 }
12828 else
12829 { # x86: 51fa:(\t)89 e5 (\t)mov %esp,%ebp
12830 # arm: 5020:(\t)e24cb004(\t)sub(\t)fp, ip, #4(\t); 0x4
12831 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 +040012832 $Interface_Impl{$LibVersion}{$CurInterface} .= $2."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012833 }
12834 }
12835 }
12836 }
12837}
12838
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012839sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012840{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012841 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012842 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12843 {
12844 if(link_symbol($Symbol, 1, "+Deps"))
12845 { # linker can find a new symbol
12846 # in the old-version library
12847 # So, it's not a new symbol
12848 next;
12849 }
12850 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012851 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012852 next;
12853 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012854 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012855 }
12856}
12857
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012858sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012859{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012860 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012861 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12862 {
12863 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012864 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012865 }
12866 if(link_symbol($Symbol, 2, "+Deps"))
12867 { # linker can find an old symbol
12868 # in the new-version library
12869 next;
12870 }
12871 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012872 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012873 next;
12874 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012875 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012876 }
12877}
12878
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012879sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012880{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012881 my $Level = $_[0];
12882 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012883 { # checking added symbols
12884 next if($CompleteSignature{2}{$Symbol}{"Private"});
12885 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012886 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012887 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012888 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012889 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012890 { # checking removed symbols
12891 next if($CompleteSignature{1}{$Symbol}{"Private"});
12892 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012893 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012894 { # skip v-tables for templates, that should not be imported by applications
12895 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012896 if(my $CName = $VTableClass{$Symbol})
12897 {
12898 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12899 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012900 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012901 next;
12902 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012903 }
12904 }
12905 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012906 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012907 }
12908 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12909 { # symbols for pure virtual methods cannot be called by clients
12910 next;
12911 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012912 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012913 }
12914}
12915
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012916sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012917{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012918 my ($LibVersion, $V) = @_;
12919 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12920 return $Cache{"checkDump"}{$LibVersion}{$V};
12921 }
12922 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012923}
12924
12925sub detectAdded_H($)
12926{
12927 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012928 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12929 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012930 if($Level eq "Source")
12931 { # remove symbol version
12932 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12933 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012934
12935 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12936 { # skip artificial constructors
12937 next;
12938 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012939 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012940 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12941 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012942 next;
12943 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012944 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012945 next;
12946 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012947 if(not defined $CompleteSignature{1}{$Symbol}
12948 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12949 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012950 if($UsedDump{2}{"SrcBin"})
12951 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012952 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012953 { # support for old and different (!) ABI dumps
12954 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12955 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012956 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012957 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012958 {
12959 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12960 {
12961 if($Lang eq "C")
12962 { # support for old ABI dumps: missed extern "C" functions
12963 next;
12964 }
12965 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012966 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012967 else
12968 {
12969 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012970 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012971 next;
12972 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012973 }
12974 }
12975 }
12976 }
12977 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012978 }
12979 }
12980}
12981
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012982sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012983{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012984 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012985 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12986 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012987 if($Level eq "Source")
12988 { # remove symbol version
12989 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12990 $Symbol=$SN;
12991 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012992 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12993 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012994 next;
12995 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012996 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012997 next;
12998 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012999 if(not defined $CompleteSignature{2}{$Symbol}
13000 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013001 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013002 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013003 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013004 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013005 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013006 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
13007 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013008 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013009 if($CheckHeadersOnly)
13010 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013011 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
13012 {
13013 if($Lang eq "C")
13014 { # support for old ABI dumps: missed extern "C" functions
13015 next;
13016 }
13017 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013018 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013019 else
13020 {
13021 if(not link_symbol($Symbol, 1, "-Deps"))
13022 { # skip removed inline symbols
13023 next;
13024 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013025 }
13026 }
13027 }
13028 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040013029 if(not checkDump(1, "2.15"))
13030 {
13031 if($Symbol=~/_IT_E\Z/)
13032 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
13033 next;
13034 }
13035 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013036 if(not $CompleteSignature{1}{$Symbol}{"Class"})
13037 {
13038 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
13039 {
13040 if(defined $Constants{2}{$Short})
13041 {
13042 my $Val = $Constants{2}{$Short}{"Value"};
13043 if(defined $Func_ShortName{2}{$Val})
13044 { # old name defined to new
13045 next;
13046 }
13047 }
13048 }
13049
13050 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013051 $RemovedInt{$Level}{$Symbol} = 1;
13052 if($Level eq "Source")
13053 { # search for a source-compatible equivalent
13054 setAlternative($Symbol, $Level);
13055 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013056 }
13057 }
13058}
13059
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013060sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013061{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013062 my $Level = $_[0];
13063 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013064 { # checking added symbols
13065 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013066 next if($CompleteSignature{2}{$Symbol}{"Private"});
13067 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013068 if($Level eq "Binary")
13069 {
13070 if($CompleteSignature{2}{$Symbol}{"InLine"})
13071 {
13072 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
13073 { # skip inline non-virtual functions
13074 next;
13075 }
13076 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013077 }
13078 else
13079 { # Source
13080 if($SourceAlternative_B{$Symbol}) {
13081 next;
13082 }
13083 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013084 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013085 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013086 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013087 { # checking removed symbols
13088 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013089 next if($CompleteSignature{1}{$Symbol}{"Private"});
13090 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013091 if($Level eq "Binary")
13092 {
13093 if($CompleteSignature{1}{$Symbol}{"InLine"})
13094 {
13095 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13096 { # skip inline non-virtual functions
13097 next;
13098 }
13099 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013100 }
13101 else
13102 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013103 if(my $Alt = $SourceAlternative{$Symbol})
13104 {
13105 if(defined $CompleteSignature{1}{$Alt}
13106 and $CompleteSignature{1}{$Symbol}{"Const"})
13107 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013108 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013109 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013110 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013111 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013112 }
13113 else
13114 { # do NOT show removed symbol
13115 next;
13116 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013117 }
13118 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013119 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013120 }
13121}
13122
13123sub addParamNames($)
13124{
13125 my $LibraryVersion = $_[0];
13126 return if(not keys(%AddIntParams));
13127 my $SecondVersion = $LibraryVersion==1?2:1;
13128 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13129 {
13130 next if(not keys(%{$AddIntParams{$Interface}}));
13131 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013132 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013133 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13134 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013135 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013136 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13137 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13138 {
13139 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13140 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13141 }
13142 }
13143 else {
13144 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13145 }
13146 }
13147 }
13148 }
13149}
13150
13151sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013152{ # detect changed typedefs to show
13153 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013154 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13155 {
13156 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013157 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13158 if(not $BName1 or isAnon($BName1)) {
13159 next;
13160 }
13161 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13162 if(not $BName2 or isAnon($BName2)) {
13163 next;
13164 }
13165 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013166 $ChangedTypedef{$Typedef} = 1;
13167 }
13168 }
13169}
13170
13171sub get_symbol_suffix($$)
13172{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013173 my ($Symbol, $Full) = @_;
13174 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013175 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013176 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013177 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013178 if(not $Full) {
13179 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13180 }
13181 return $Suffix;
13182}
13183
13184sub get_symbol_prefix($$)
13185{
13186 my ($Symbol, $LibVersion) = @_;
13187 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13188 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13189 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013190 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013191 }
13192 return $ShortName;
13193}
13194
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013195sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013196{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013197 my $Symbol = $_[0];
13198 my $PSymbol = $Symbol;
13199 if(not defined $CompleteSignature{2}{$PSymbol}
13200 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13201 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13202 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013203 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013204 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013205 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013206 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013207 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13208 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013209 {
13210 if(defined $CompleteSignature{2}{$PSymbol}
13211 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13212 {
13213 $SourceAlternative{$Symbol} = $PSymbol;
13214 $SourceAlternative_B{$PSymbol} = $Symbol;
13215 if(not defined $CompleteSignature{1}{$PSymbol}
13216 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13217 $SourceReplacement{$Symbol} = $PSymbol;
13218 }
13219 }
13220 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013221 }
13222 else
13223 {
13224 foreach my $Sp ("KV", "VK", "K", "V")
13225 {
13226 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13227 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13228 {
13229 if(defined $CompleteSignature{2}{$PSymbol}
13230 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13231 {
13232 $SourceAlternative{$Symbol} = $PSymbol;
13233 $SourceAlternative_B{$PSymbol} = $Symbol;
13234 if(not defined $CompleteSignature{1}{$PSymbol}
13235 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13236 $SourceReplacement{$Symbol} = $PSymbol;
13237 }
13238 }
13239 }
13240 $PSymbol = $Symbol;
13241 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013242 }
13243 }
13244 }
13245 return "";
13246}
13247
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013248sub getSymKind($$)
13249{
13250 my ($Symbol, $LibVersion) = @_;
13251 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13252 {
13253 return "Global_Data";
13254 }
13255 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13256 {
13257 return "Method";
13258 }
13259 return "Function";
13260}
13261
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013262sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013263{
13264 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013265 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013266
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013267 mergeBases($Level);
13268
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013269 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013270 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013271 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013272 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013273 next;
13274 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013275 if(defined $CompleteSignature{1}{$Symbol}
13276 and $CompleteSignature{1}{$Symbol}{"Header"})
13277 { # double-check added symbol
13278 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013279 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013280 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013281 next;
13282 }
13283 if($Symbol=~/\A(_Z|\?)/)
13284 { # C++
13285 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13286 }
13287 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13288 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013289 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13290 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013291 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013292 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013293 {
13294 if($TName_Tid{1}{$AffectedClass_Name})
13295 { # class should exist in previous version
13296 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13297 { # old v-table is NOT copied by old applications
13298 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13299 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013300 "Target"=>get_Signature($Symbol, 2),
13301 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013302 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013303 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013305 }
13306 }
13307 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013308 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13309 { # check all removed exported symbols
13310 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013311 next;
13312 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013313 if(defined $CompleteSignature{2}{$Symbol}
13314 and $CompleteSignature{2}{$Symbol}{"Header"})
13315 { # double-check removed symbol
13316 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013317 }
13318 if($CompleteSignature{1}{$Symbol}{"Private"})
13319 { # skip private methods
13320 next;
13321 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013322 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013323 next;
13324 }
13325 $CheckedSymbols{$Level}{$Symbol} = 1;
13326 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13327 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013328 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13329 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013330 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013331 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13332 {
13333 if($TName_Tid{2}{$AffectedClass_Name})
13334 { # class should exist in newer version
13335 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13336 { # old v-table is NOT copied by old applications
13337 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13338 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013339 "Target"=>get_Signature($OverriddenMethod, 1),
13340 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013341 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013342 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013344 }
13345 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013346 if($Level eq "Binary"
13347 and $OSgroup eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013348 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013349 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013350 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013351 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013352 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013353 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013354 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013355 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013356 {
13357 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13358 "Target"=>$tr_name{$Symbol},
13359 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013360 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013361 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013362 else
13363 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013364 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013365 "Target"=>$tr_name{$Symbol},
13366 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013367 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013368 }
13369 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013370 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013371 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013372 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013373 {
13374 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13375 "Target"=>$tr_name{$Symbol},
13376 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013377 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013378 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013379 else
13380 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013381 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013382 "Target"=>$tr_name{$Symbol},
13383 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013384 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013385 }
13386 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013387 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13388 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13389 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13390 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13391 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013392 {
13393 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013394 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013395 $ProblemType = "Global_Data_Symbol_Changed_Type";
13396 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013397 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13398 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013399 "Old_Type"=>$RTName1,
13400 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013401 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013402 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013403 }
13404 }
13405 }
13406 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013407 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013408 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013409 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013410 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013411 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013412 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013413 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013414 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13415 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013416 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013417 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013418 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013419 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013420 }
13421 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013422 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13423 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013424 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013425 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013426 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013427 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013428 }
13429 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013430 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013431 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013432 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013433 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013434 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013435 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013436 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013437 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013438 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013439 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013440 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013441 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013442 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013443 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013444 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013445 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013446 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013447 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013448 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013449 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013450 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013451 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013452 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013453 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013454 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013455 { # "volatile" to non-"volatile"
13456
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013457 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013458 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013459 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013460 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013461 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013462 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013463 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013464 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013465 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013466 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013467 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013468 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013469 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013470 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013471 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013472 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013473 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013474 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13475 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013476 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013477 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013478 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013479 }
13480 }
13481 }
13482 }
13483 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013484 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13485 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013486 $CurrentSymbol = $Symbol;
13487
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013488 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13489 if($Level eq "Source")
13490 { # remove symbol version
13491 $Symbol=$SN;
13492 }
13493 else
13494 { # Binary
13495 if(not $SV)
13496 { # symbol without version
13497 if(my $VSym = $SymVer{1}{$Symbol})
13498 { # the symbol is linked with versioned symbol
13499 if($CompleteSignature{2}{$VSym}{"MnglName"})
13500 { # show report for symbol@ver only
13501 next;
13502 }
13503 elsif(not link_symbol($VSym, 2, "-Deps"))
13504 { # changed version: sym@v1 to sym@v2
13505 # do NOT show report for symbol
13506 next;
13507 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013508 }
13509 }
13510 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013511 my $PSymbol = $Symbol;
13512 if($Level eq "Source"
13513 and my $S = $SourceReplacement{$Symbol})
13514 { # take a source-compatible replacement function
13515 $PSymbol = $S;
13516 }
13517 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013518 { # private symbols
13519 next;
13520 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013521 if(not defined $CompleteSignature{1}{$Symbol}
13522 or not defined $CompleteSignature{2}{$PSymbol})
13523 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013524 next;
13525 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013526 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13527 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13528 { # no mangled name
13529 next;
13530 }
13531 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13532 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013533 { # without a header
13534 next;
13535 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013536
13537 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13538 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13539 { # became pure
13540 next;
13541 }
13542 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13543 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13544 { # became non-pure
13545 next;
13546 }
13547
13548 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13549 { # exported, target, inline virtual and pure virtual
13550 next;
13551 }
13552 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13553 { # exported, target, inline virtual and pure virtual
13554 next;
13555 }
13556
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013557 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013558 {
13559 if($CompleteSignature{1}{$Symbol}{"Data"}
13560 and $CompleteSignature{2}{$PSymbol}{"Data"})
13561 {
13562 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13563 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13564 if(defined $Value1)
13565 {
13566 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13567 if(defined $Value2)
13568 {
13569 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13570 if($Value1 ne $Value2)
13571 {
13572 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13573 "Old_Value"=>$Value1,
13574 "New_Value"=>$Value2,
13575 "Target"=>get_Signature($Symbol, 1) );
13576 }
13577 }
13578 }
13579 }
13580 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013581
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013582 if($CompleteSignature{2}{$PSymbol}{"Private"})
13583 {
13584 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13585 "Target"=>get_Signature_M($PSymbol, 2) );
13586 }
13587 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13588 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13589 {
13590 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13591 "Target"=>get_Signature_M($PSymbol, 2) );
13592 }
13593 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13594 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13595 {
13596 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13597 "Target"=>get_Signature_M($PSymbol, 2) );
13598 }
13599
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013600 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013601 mergeVirtualTables($Symbol, $Level);
13602
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013603 if($COMPILE_ERRORS)
13604 { # if some errors occurred at the compiling stage
13605 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013606 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013607 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013608 { # missed information about parameters in newer version
13609 next;
13610 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013611 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013612 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013613 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013614 next;
13615 }
13616 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013617 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013618 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013619 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013620 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13621 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013622 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13623 "Target"=>get_Signature($Symbol, 1)
13624 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013625 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013626 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013627 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13628 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013629 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013630 "Target"=>get_Signature($Symbol, 1)
13631 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013632 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013633 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13634 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013635 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013636 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013637 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013638 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13639 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13640 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013641 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013642 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013643 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13644 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013645 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013646 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013647 my $ProblemType = "Virtual_Method_Position";
13648 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13649 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013650 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013651 if(isUsedClass($Class_Id, 1, $Level))
13652 {
13653 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013654 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013655 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013656 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13657 next;
13658 }
13659 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013660 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013661 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13662 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013663 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013664 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013665 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013666 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013667 }
13668 }
13669 }
13670 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013671 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13672 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013673 { # do NOT check type changes in pure virtuals
13674 next;
13675 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013676 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013677 if($Symbol=~/\A(_Z|\?)/
13678 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013679 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013680 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013681 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013682 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013683 }
13684 }
13685 else
13686 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013687 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013688 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013689 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013690 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13691 last if($PType2_Name eq "...");
13692 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13693 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013694 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013695 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013696 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013697 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13698 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013699 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13700 $ParamPos_Prev = "lost";
13701 }
13702 }
13703 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013704 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013705 }
13706 if($ParamPos_Prev eq "lost")
13707 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013708 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013709 {
13710 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013711 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013712 $ProblemType = "Added_Unnamed_Parameter";
13713 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013714 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013715 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013716 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013717 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013718 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013719 }
13720 else
13721 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013722 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013723 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013724 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013725 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13726 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013727 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013728 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013729 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013730 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013731 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013732 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013733 "Param_Type"=>$PType2_Name,
13734 "Old_Value"=>$PName_Old,
13735 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013736 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013737 }
13738 }
13739 else
13740 {
13741 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013742 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013743 $ProblemType = "Added_Middle_Unnamed_Parameter";
13744 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013745 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013746 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013747 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013748 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013749 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013750 }
13751 }
13752 }
13753 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013754 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013755 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013756 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013757 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013758 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013759 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013760 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013761 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013762 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013763 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13764 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013765 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013766 }
13767 }
13768 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013769 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013770 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013771 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013772 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13773 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013774 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13775 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013776 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013777 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013778 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013779 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13780 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013781 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13782 $ParamPos_New = "lost";
13783 }
13784 }
13785 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013786 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013787 }
13788 if($ParamPos_New eq "lost")
13789 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013790 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013791 {
13792 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013793 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013794 $ProblemType = "Removed_Unnamed_Parameter";
13795 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013796 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013797 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013798 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013799 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013800 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013801 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013802 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013803 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013804 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013805 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013806 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013807 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013808 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013809 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013810 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013811 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013812 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013813 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013814 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013815 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013816 "Old_Value"=>$PName,
13817 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013818 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013819 }
13820 }
13821 else
13822 {
13823 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013824 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013825 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13826 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013827 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013828 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013829 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013830 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013831 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013832 }
13833 }
13834 }
13835 }
13836 }
13837 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013838 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13839 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013840 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013841
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013842 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013843 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013844 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13845 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013846 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013847
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013848 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013849 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013850 if($SubProblemType eq "Return_Type_And_Size") {
13851 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13852 }
13853 elsif($SubProblemType eq "Return_Type_Format") {
13854 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13855 }
13856 else {
13857 $ProblemTypes{"Global_Data_Type"} = 1;
13858 }
13859
13860 # quals
13861 if($SubProblemType eq "Return_Type"
13862 or $SubProblemType eq "Return_Type_And_Size"
13863 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013864 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013865 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13866 { # const to non-const
13867 if($RR==2) {
13868 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13869 }
13870 else {
13871 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13872 }
13873 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013874 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013875 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13876 { # non-const to const
13877 if($RA==2) {
13878 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13879 }
13880 else {
13881 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13882 }
13883 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013884 }
13885 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013886 }
13887 else
13888 {
13889 # quals
13890 if($SubProblemType eq "Return_Type"
13891 or $SubProblemType eq "Return_Type_And_Size"
13892 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013893 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013894 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013895 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013896 if(addedQual($Old_Value, $New_Value, "volatile"))
13897 {
13898 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13899 if($Level ne "Source"
13900 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13901 $ProblemTypes{"Return_Type"} = 1;
13902 }
13903 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013904 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013905 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13906 {
13907 if($RA==2) {
13908 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13909 }
13910 else {
13911 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13912 }
13913 if($Level ne "Source"
13914 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13915 $ProblemTypes{"Return_Type"} = 1;
13916 }
13917 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013918 }
13919 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013920 if($Level eq "Binary"
13921 and not $CompleteSignature{1}{$Symbol}{"Data"})
13922 {
13923 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13924 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13925 { # if one of the architectures is unknown
13926 # then set other arhitecture to unknown too
13927 ($Arch1, $Arch2) = ("unknown", "unknown");
13928 }
13929 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013930 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013931 {
13932 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13933 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13934 }
13935 else
13936 {
13937 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13938 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13939 }
13940
13941 if($SubProblemType eq "Return_Type_Became_Void")
13942 {
13943 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13944 { # parameters stack has been affected
13945 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013946 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013947 }
13948 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013949 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013950 }
13951 }
13952 }
13953 elsif($SubProblemType eq "Return_Type_From_Void")
13954 {
13955 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13956 { # parameters stack has been affected
13957 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013958 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013959 }
13960 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013961 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013962 }
13963 }
13964 }
13965 elsif($SubProblemType eq "Return_Type"
13966 or $SubProblemType eq "Return_Type_And_Size"
13967 or $SubProblemType eq "Return_Type_Format")
13968 {
13969 if($Conv1{"Method"} ne $Conv2{"Method"})
13970 {
13971 if($Conv1{"Method"} eq "stack")
13972 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013973 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013974 }
13975 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013976 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013977 }
13978 }
13979 else
13980 {
13981 if($Conv1{"Method"} eq "reg")
13982 {
13983 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13984 {
13985 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013986 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013987 }
13988 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013989 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013990 }
13991 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013992 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013993 }
13994 }
13995 }
13996 }
13997 }
13998 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013999
14000 if(not keys(%ProblemTypes))
14001 { # default
14002 $ProblemTypes{$SubProblemType} = 1;
14003 }
14004
14005 foreach my $ProblemType (keys(%ProblemTypes))
14006 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014007 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014009 }
14010 if($ReturnType1_Id and $ReturnType2_Id)
14011 {
14012 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014013 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
14014
14015 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014016
14017 if($CompleteSignature{1}{$Symbol}{"Data"})
14018 {
14019 if($Level eq "Binary")
14020 {
14021 if(get_PLevel($ReturnType1_Id, 1)==0)
14022 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014023 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014024 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014025
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014026 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
14027 {
14028 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014029 {
14030 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
14031 {
14032 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
14033 last;
14034 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014035 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014036 }
14037 }
14038 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014039 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014040 {
14041 if(defined $GlobalDataObject{1}{$Symbol}
14042 and defined $GlobalDataObject{2}{$Symbol})
14043 {
14044 my $Old_Size = $GlobalDataObject{1}{$Symbol};
14045 my $New_Size = $GlobalDataObject{2}{$Symbol};
14046 if($Old_Size!=$New_Size)
14047 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014048 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014049 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014050 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014051 }
14052 }
14053 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014054 }
14055 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014056
14057 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014058 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014059 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014060 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014061 my $NewLocation = "retval";
14062 if($SubLocation and $SubLocation ne "retval") {
14063 $NewLocation = "retval->".$SubLocation;
14064 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014065 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
14066 }
14067 }
14068
14069 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
14070 {
14071 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
14072 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014073 my $NewLocation = "retval";
14074 if($SubLocation and $SubLocation ne "retval") {
14075 $NewLocation = "retval->".$SubLocation;
14076 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014077 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014078 }
14079 }
14080 }
14081
14082 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014083 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
14084 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
14085 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014086 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014087 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014088 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
14089 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014090 if($ThisPtr1_Id and $ThisPtr2_Id)
14091 {
14092 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014093 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14094 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014095 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014096 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014097 {
14098 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014099 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014100 }
14101 }
14102 }
14103 }
14104 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014105 if($Level eq "Binary") {
14106 mergeVTables($Level);
14107 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014108 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14109 $CheckedSymbols{$Level}{$Symbol} = 1;
14110 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014111}
14112
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014113sub rmQuals($$)
14114{
14115 my ($Value, $Qual) = @_;
14116 if(not $Qual) {
14117 return $Value;
14118 }
14119 if($Qual eq "all")
14120 { # all quals
14121 $Qual = "const|volatile|restrict";
14122 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014123 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014124 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014125 }
14126 return $Value;
14127}
14128
14129sub cmpBTypes($$$$)
14130{
14131 my ($T1, $T2, $V1, $V2) = @_;
14132 $T1 = uncover_typedefs($T1, $V1);
14133 $T2 = uncover_typedefs($T2, $V2);
14134 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14135}
14136
14137sub addedQual($$$)
14138{
14139 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014140 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014141}
14142
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014143sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014144{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014145 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014146 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014147}
14148
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014149sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014150{
14151 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14152 $Old_Value = uncover_typedefs($Old_Value, $V1);
14153 $New_Value = uncover_typedefs($New_Value, $V2);
14154 if($Old_Value eq $New_Value)
14155 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014156 return 0;
14157 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014158 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014159 { # without a qual
14160 return 0;
14161 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014162 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014163 { # became non-qual
14164 return 1;
14165 }
14166 else
14167 {
14168 my @BQ1 = getQualModel($Old_Value, $Qual);
14169 my @BQ2 = getQualModel($New_Value, $Qual);
14170 foreach (0 .. $#BQ1)
14171 { # removed qual
14172 if($BQ1[$_]==1
14173 and $BQ2[$_]!=1)
14174 {
14175 return 2;
14176 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014177 }
14178 }
14179 return 0;
14180}
14181
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014182sub getQualModel($$)
14183{
14184 my ($Value, $Qual) = @_;
14185 if(not $Qual) {
14186 return $Value;
14187 }
14188
14189 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014190 while($Value=~/(\w+)/ and $1 ne $Qual) {
14191 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014192 }
14193 $Value=~s/[^\*\&\w]+//g;
14194
14195 # modeling
14196 # int*const*const == 011
14197 # int**const == 001
14198 my @Model = ();
14199 my @Elems = split(/[\*\&]/, $Value);
14200 if(not @Elems) {
14201 return (0);
14202 }
14203 foreach (@Elems)
14204 {
14205 if($_ eq $Qual) {
14206 push(@Model, 1);
14207 }
14208 else {
14209 push(@Model, 0);
14210 }
14211 }
14212
14213 return @Model;
14214}
14215
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014216my %StringTypes = map {$_=>1} (
14217 "char*",
14218 "char const*"
14219);
14220
14221my %CharTypes = map {$_=>1} (
14222 "char",
14223 "char const"
14224);
14225
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014226sub showVal($$$)
14227{
14228 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014229 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014230 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014231 if(substr($Value, 0, 2) eq "_Z")
14232 {
14233 if(my $Unmangled = $tr_name{$Value}) {
14234 return $Unmangled;
14235 }
14236 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014237 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014238 { # strings
14239 return "\"$Value\"";
14240 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014241 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014242 { # characters
14243 return "\'$Value\'";
14244 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014245 if($Value eq "")
14246 { # other
14247 return "\'\'";
14248 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014249 return $Value;
14250}
14251
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014252sub getRegs($$$)
14253{
14254 my ($LibVersion, $Symbol, $Pos) = @_;
14255
14256 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14257 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014258 my %Regs = ();
14259 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14260 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014261 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014262 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14263 }
14264 }
14265
14266 return join(", ", sort keys(%Regs));
14267 }
14268
14269 return undef;
14270}
14271
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014272sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014273{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014274 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014275 if(not $Symbol) {
14276 return;
14277 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014278 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14279 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14280 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14281 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014282 if(not $PType1_Id
14283 or not $PType2_Id) {
14284 return;
14285 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014286
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014287 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014288 { # do not merge "this"
14289 if($PName1 eq "this" or $PName2 eq "this") {
14290 return;
14291 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014292 }
14293
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014294 my %Type1 = get_Type($PType1_Id, 1);
14295 my %Type2 = get_Type($PType2_Id, 2);
14296 my %BaseType1 = get_BaseType($PType1_Id, 1);
14297 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014298 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014299
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014300 if($Level eq "Binary")
14301 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014302 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014303 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14304 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14305 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14306 {
14307 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014308 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014309 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014310 }
14311 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14312 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14313 {
14314 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014315 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014316 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014317 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014318 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014319
14320 if(defined $UsedDump{1}{"DWARF"}
14321 and defined $UsedDump{2}{"DWARF"})
14322 {
14323 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14324 {
14325 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14326 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14327 if($Old_Regs and $New_Regs)
14328 {
14329 if($Old_Regs ne $New_Regs)
14330 {
14331 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14332 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014333 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014334 "Old_Value"=>$Old_Regs,
14335 "New_Value"=>$New_Regs );
14336 }
14337 }
14338 elsif($Old_Regs and not $New_Regs)
14339 {
14340 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14341 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014342 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014343 "Old_Value"=>$Old_Regs );
14344 }
14345 elsif(not $Old_Regs and $New_Regs)
14346 {
14347 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14348 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014349 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014350 "New_Value"=>$New_Regs );
14351 }
14352 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14353 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14354 {
14355 if($Old_Offset ne $New_Offset)
14356 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014357 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14358 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14359
14360 $Old_Offset = $Old_Offset - $Start1;
14361 $New_Offset = $New_Offset - $Start2;
14362
14363 if($Old_Offset ne $New_Offset)
14364 {
14365 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14366 "Target"=>$PName1,
14367 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14368 "Old_Value"=>$Old_Offset,
14369 "New_Value"=>$New_Offset );
14370 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014371 }
14372 }
14373 }
14374 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014375 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014376 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14377 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014378 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014379 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014380 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14381 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014382 if(not checkDump(1, "2.13")
14383 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014384 { # support for old ABI dumps
14385 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014386 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014387 if($Type1{"Name"} eq "bool"
14388 and $Value_Old eq "false" and $Value_New eq "0")
14389 { # int class::method ( bool p = 0 );
14390 # old ABI dumps: "false"
14391 # new ABI dumps: "0"
14392 $Value_Old = "0";
14393 }
14394 }
14395 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014396 if(not checkDump(1, "2.18")
14397 and checkDump(2, "2.18"))
14398 { # support for old ABI dumps
14399 if(not defined $Value_Old
14400 and substr($Value_New, 0, 2) eq "_Z") {
14401 $Value_Old = $Value_New;
14402 }
14403 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014404 if(defined $Value_Old)
14405 {
14406 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14407 if(defined $Value_New)
14408 {
14409 $Value_New = showVal($Value_New, $PType2_Id, 2);
14410 if($Value_Old ne $Value_New)
14411 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014412 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014413 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014414 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014415 "Old_Value"=>$Value_Old,
14416 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014417 }
14418 }
14419 else
14420 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014421 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014422 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014423 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014424 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014425 }
14426 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014427 elsif(defined $Value_New)
14428 {
14429 $Value_New = showVal($Value_New, $PType2_Id, 2);
14430 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14431 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014432 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014433 "New_Value"=>$Value_New );
14434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014435 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014436
14437 if($ChkRnmd)
14438 {
14439 if($PName1 and $PName2 and $PName1 ne $PName2
14440 and $PType1_Id!=-1 and $PType2_Id!=-1
14441 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14442 { # except unnamed "..." value list (Id=-1)
14443 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14444 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014445 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014446 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14447 "Old_Value"=>$PName1,
14448 "New_Value"=>$PName2,
14449 "New_Signature"=>get_Signature($Symbol, 2) );
14450 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014451 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014453 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014454 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014455
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014456 foreach my $SubProblemType (keys(%SubProblems))
14457 { # add new problems, remove false alarms
14458 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14459 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014460
14461 # quals
14462 if($SubProblemType eq "Parameter_Type"
14463 or $SubProblemType eq "Parameter_Type_And_Size"
14464 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014465 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014466 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014467 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014468 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014469 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014470 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014471 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14472 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14473 }
14474 }
14475 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14476 {
14477 if(removedQual($Old_Value, $New_Value, "volatile")) {
14478 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014479 }
14480 }
14481 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14482 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14483 { # int to "int const"
14484 delete($SubProblems{$SubProblemType});
14485 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014486 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014487 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14488 { # "int const" to int
14489 delete($SubProblems{$SubProblemType});
14490 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014491 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14492 { # "const" to non-"const"
14493 if($RR==2) {
14494 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14495 }
14496 else {
14497 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14498 }
14499 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014500 }
14501 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014502
14503 if($Level eq "Source")
14504 {
14505 foreach my $SubProblemType (keys(%SubProblems))
14506 {
14507 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14508 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14509
14510 if($SubProblemType eq "Parameter_Type")
14511 {
14512 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14513 delete($SubProblems{$SubProblemType});
14514 }
14515 }
14516 }
14517 }
14518
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014519 foreach my $SubProblemType (keys(%SubProblems))
14520 { # modify/register problems
14521 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14522 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014523 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14524 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014525
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014526 my $NewProblemType = $SubProblemType;
14527 if($Old_Value eq "..." and $New_Value ne "...")
14528 { # change from "..." to "int"
14529 if($ParamPos1==0)
14530 { # ISO C requires a named argument before "..."
14531 next;
14532 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014533 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014534 }
14535 elsif($New_Value eq "..." and $Old_Value ne "...")
14536 { # change from "int" to "..."
14537 if($ParamPos2==0)
14538 { # ISO C requires a named argument before "..."
14539 next;
14540 }
14541 $NewProblemType = "Parameter_Became_VaList";
14542 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014543 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014544 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014545 {
14546 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014547 if($Arch1 eq "unknown"
14548 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014549 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014550 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014551 ($Arch1, $Arch2) = ("unknown", "unknown");
14552 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014553 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014554 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014555 { # real
14556 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14557 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14558 }
14559 else
14560 { # model
14561 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14562 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14563 }
14564 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014565 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014566 if($Conv1{"Method"} eq "stack")
14567 {
14568 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14569 $NewProblemType = "Parameter_Type_And_Stack";
14570 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014571 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014572 elsif($Conv1{"Method"} eq "reg")
14573 {
14574 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14575 $NewProblemType = "Parameter_Type_And_Register";
14576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014577 }
14578 }
14579 else
14580 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014581 if($Conv1{"Method"} eq "stack") {
14582 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014583 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014584 elsif($Conv1{"Method"} eq "register") {
14585 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014586 }
14587 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014588 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14589 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014590 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014591 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014592 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014593 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014594 "New_Signature"=>get_Signature($Symbol, 2) );
14595 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014596 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014597
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014598 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014599
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014600 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014601 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14602 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014603 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014604 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014605 {
14606 my $NewProblemType = $SubProblemType;
14607 if($SubProblemType eq "DataType_Size")
14608 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014609 if($Type1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014610 { # stack has been affected
14611 $NewProblemType = "DataType_Size_And_Stack";
14612 }
14613 }
14614 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014615 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014616 }
14617 }
14618}
14619
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014620sub find_ParamPair_Pos_byName($$$)
14621{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014622 my ($Name, $Symbol, $LibVersion) = @_;
14623 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014624 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014625 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14626 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014627 {
14628 return $ParamPos;
14629 }
14630 }
14631 return "lost";
14632}
14633
14634sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14635{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014636 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014637 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014638 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014639 {
14640 next if($Order eq "backward" and $ParamPos>$MediumPos);
14641 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014642 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14643 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014644 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014645 push(@Positions, $ParamPos);
14646 }
14647 }
14648 return @Positions;
14649}
14650
14651sub getTypeIdByName($$)
14652{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014653 my ($TypeName, $LibVersion) = @_;
14654 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014655}
14656
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014657sub diffTypes($$$)
14658{
14659 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14660 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14661 }
14662 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14663 { # skip recursive declarations
14664 return 0;
14665 }
14666
14667 pushType($_[0], $_[1], \@RecurTypes_Diff);
14668 my $Diff = diffTypes_I(@_);
14669 pop(@RecurTypes_Diff);
14670
14671 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14672}
14673
14674sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014675{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014676 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014677
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014678 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14679 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014680
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014681 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14682 { # equal types
14683 return 0;
14684 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014685 if($Type1_Pure{"Name"} eq "void")
14686 { # from void* to something
14687 return 0;
14688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014689 if($Type1_Pure{"Name"}=~/\*/
14690 or $Type2_Pure{"Name"}=~/\*/)
14691 { # compared in detectTypeChange()
14692 return 0;
14693 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014694
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014695 my %FloatType = map {$_=>1} (
14696 "float",
14697 "double",
14698 "long double"
14699 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014700
14701 my $T1 = $Type1_Pure{"Type"};
14702 my $T2 = $Type2_Pure{"Type"};
14703
14704 if($T1 eq "Struct"
14705 and $T2 eq "Class")
14706 { # compare as data structures
14707 $T2 = "Struct";
14708 }
14709
14710 if($T1 eq "Class"
14711 and $T2 eq "Struct")
14712 { # compare as data structures
14713 $T1 = "Struct";
14714 }
14715
14716 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014717 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014718 if($T1 eq "Intrinsic"
14719 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014720 { # "int" to "enum"
14721 return 0;
14722 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014723 elsif($T2 eq "Intrinsic"
14724 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014725 { # "enum" to "int"
14726 return 0;
14727 }
14728 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014729 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014730 # ...
14731 return 1;
14732 }
14733 }
14734 else
14735 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014736 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014737 {
14738 if($FloatType{$Type1_Pure{"Name"}}
14739 or $FloatType{$Type2_Pure{"Name"}})
14740 { # "float" to "double"
14741 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014742 if($Level eq "Source")
14743 { # Safe
14744 return 0;
14745 }
14746 else {
14747 return 1;
14748 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014749 }
14750 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014751 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014752 {
14753 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14754 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014755 if(not @Membs1
14756 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014757 { # private
14758 return 0;
14759 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014760 if($#Membs1!=$#Membs2)
14761 { # different number of elements
14762 return 1;
14763 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014764 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014765 {
14766 foreach my $Pos (@Membs1)
14767 { # compare elements by name and value
14768 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14769 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14770 { # different names
14771 return 1;
14772 }
14773 }
14774 }
14775 else
14776 {
14777 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014778 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014779 if($Level eq "Source")
14780 {
14781 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14782 { # different names
14783 return 1;
14784 }
14785 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014786
14787 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14788 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14789
14790 if($MT1{"Name"} ne $MT2{"Name"}
14791 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14792 {
14793 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14794 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14795
14796 if($PL1 ne $PL2)
14797 { # different pointer level
14798 return 1;
14799 }
14800
14801 # compare base types
14802 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14803 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14804
14805 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14806 { # different types
14807 return 1;
14808 }
14809 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014810 }
14811 }
14812 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014813 else
14814 {
14815 # TODO: arrays, etc.
14816 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014817 }
14818 return 0;
14819}
14820
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014821sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014822{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014823 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014824 if(not $Type1_Id or not $Type2_Id) {
14825 return ();
14826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014827 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014828 my %Type1 = get_Type($Type1_Id, 1);
14829 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014830 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14831 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14832 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14833 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 +040014834
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014835 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14836 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014837 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14838 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14839 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14840 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14841 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14842 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14843 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014844 if($Type1{"Name"} eq $Type2{"Name"})
14845 {
14846 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14847 { # will be reported in mergeTypes() as typedef problem
14848 return ();
14849 }
14850 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14851 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14852 if(%Typedef_1 and %Typedef_2)
14853 {
14854 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14855 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14856 { # const Typedef
14857 return ();
14858 }
14859 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014860 }
14861 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14862 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014863 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014864 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14865 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014866 {
14867 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14868 "Old_Value"=>$Type1_Base{"Name"},
14869 "New_Value"=>$Type2_Base{"Name"},
14870 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014871 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014872 }
14873 else
14874 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014875 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014876 { # format change
14877 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14878 "Old_Value"=>$Type1_Base{"Name"},
14879 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014880 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014881 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014882 }
14883 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14884 {
14885 %{$LocalProblems{$Prefix."_BaseType"}}=(
14886 "Old_Value"=>$Type1_Base{"Name"},
14887 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014888 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014889 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014890 }
14891 }
14892 }
14893 }
14894 elsif($Type1{"Name"} ne $Type2{"Name"})
14895 { # type change
14896 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14897 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014898 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014899 and $Type1_Pure{"Name"} eq "void")
14900 {
14901 %{$LocalProblems{"Return_Type_From_Void"}}=(
14902 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014903 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014904 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014905 elsif($Prefix eq "Return"
14906 and $Type2_Pure{"Name"} eq "void")
14907 {
14908 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14909 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014910 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014911 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014912 else
14913 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014914 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014915 and $Type1{"Size"} and $Type2{"Size"}
14916 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014917 {
14918 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14919 "Old_Value"=>$Type1{"Name"},
14920 "New_Value"=>$Type2{"Name"},
14921 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014922 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014923 }
14924 else
14925 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014926 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014927 { # format change
14928 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14929 "Old_Value"=>$Type1{"Name"},
14930 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014931 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014932 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014933 }
14934 elsif(tNameLock($Type1_Id, $Type2_Id))
14935 { # FIXME: correct this condition
14936 %{$LocalProblems{$Prefix."_Type"}}=(
14937 "Old_Value"=>$Type1{"Name"},
14938 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014939 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014940 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014941 }
14942 }
14943 }
14944 }
14945 }
14946 if($Type1_PLevel!=$Type2_PLevel)
14947 {
14948 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14949 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14950 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014951 if($Level eq "Source")
14952 {
14953 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014954 "Old_Value"=>$Type1_PLevel,
14955 "New_Value"=>$Type2_PLevel);
14956 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014957 else
14958 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014959 if($Type2_PLevel>$Type1_PLevel)
14960 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014961 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14962 "Old_Value"=>$Type1_PLevel,
14963 "New_Value"=>$Type2_PLevel);
14964 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014965 else
14966 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014967 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14968 "Old_Value"=>$Type1_PLevel,
14969 "New_Value"=>$Type2_PLevel);
14970 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014971 }
14972 }
14973 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014974 if($Type1_Pure{"Type"} eq "Array"
14975 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014976 { # base_type[N] -> base_type[N]
14977 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014978 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014979 foreach my $SubProblemType (keys(%SubProblems))
14980 {
14981 $SubProblemType=~s/_Type/_BaseType/g;
14982 next if(defined $LocalProblems{$SubProblemType});
14983 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14984 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14985 }
14986 }
14987 }
14988 return %LocalProblems;
14989}
14990
14991sub tNameLock($$)
14992{
14993 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014994 my $Changed = 0;
14995 if(differentDumps("G"))
14996 { # different GCC versions
14997 $Changed = 1;
14998 }
14999 elsif(differentDumps("V"))
15000 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015001 if(not checkDump(1, "2.20")
15002 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015003 { # latest names update
15004 # 2.6: added restrict qualifier
15005 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015006 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015007 $Changed = 1;
15008 }
15009 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015010
15011 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
15012 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
15013
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015014 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
15015 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
15016
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015017 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015018 { # different formats
15019 if($UseOldDumps)
15020 { # old dumps
15021 return 0;
15022 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015023
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015024 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015025 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015026 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015027 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015028 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015029 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015030 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015031 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015032 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
15033 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
15034 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015035 { # equal base types
15036 return 0;
15037 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015038
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015039 if(not checkDump(1, "2.13")
15040 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015041 { # broken array names in ABI dumps < 2.13
15042 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015043 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015044 return 0;
15045 }
15046 }
15047
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015048 if(not checkDump(1, "2.6")
15049 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015050 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015051 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015052 and $TN2=~/\brestrict\b/) {
15053 return 0;
15054 }
15055 }
15056
15057 if(not checkDump(1, "2.20")
15058 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015059 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015060 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15061 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015062 return 0;
15063 }
15064 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015065 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015066 else
15067 {
15068 # typedef struct {...} type_t
15069 # typedef struct type_t {...} type_t
15070 if(index($TN1, " ".$TN2)!=-1)
15071 {
15072 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15073 return 0;
15074 }
15075 }
15076 if(index($TN2, " ".$TN1)!=-1)
15077 {
15078 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15079 return 0;
15080 }
15081 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015082
15083 if($TT1 eq "FuncPtr"
15084 and $TT2 eq "FuncPtr")
15085 {
15086 my $TN1_C = $TN1;
15087 my $TN2_C = $TN2;
15088
15089 $TN1_C=~s/\b(struct|union) //g;
15090 $TN2_C=~s/\b(struct|union) //g;
15091
15092 if($TN1_C eq $TN2_C) {
15093 return 0;
15094 }
15095 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015096 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015097
15098 my ($N1, $N2) = ($TN1, $TN2);
15099 $N1=~s/\b(struct|union) //g;
15100 $N2=~s/\b(struct|union) //g;
15101
15102 if($N1 eq $N2)
15103 { # QList<struct QUrl> and QList<QUrl>
15104 return 0;
15105 }
15106
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015107 return 1;
15108}
15109
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015110sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015111{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015112 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015113 if(defined $Cache{"differentDumps"}{$Check}) {
15114 return $Cache{"differentDumps"}{$Check};
15115 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015116 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015117 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015118 if($Check eq "G")
15119 {
15120 if(getGccVersion(1) ne getGccVersion(2))
15121 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015122 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015123 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015124 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015125 if($Check eq "V")
15126 {
15127 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15128 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15129 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015130 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015131 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015133 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015134 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015135}
15136
15137sub formatVersion($$)
15138{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015139 my ($V, $Digits) = @_;
15140 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015141 return join(".", splice(@Elems, 0, $Digits));
15142}
15143
15144sub htmlSpecChars($)
15145{
15146 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015147 if(not $Str) {
15148 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015149 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015150 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15151 $Str=~s/</&lt;/g;
15152 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15153 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015154 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15155 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015156 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015157 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015158 $Str=~s/\n/<br\/>/g;
15159 $Str=~s/\"/&quot;/g;
15160 $Str=~s/\'/&#39;/g;
15161 return $Str;
15162}
15163
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015164sub xmlSpecChars($)
15165{
15166 my $Str = $_[0];
15167 if(not $Str) {
15168 return $Str;
15169 }
15170
15171 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15172 $Str=~s/</&lt;/g;
15173 $Str=~s/>/&gt;/g;
15174
15175 $Str=~s/\"/&quot;/g;
15176 $Str=~s/\'/&#39;/g;
15177
15178 return $Str;
15179}
15180
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015181sub xmlSpecChars_R($)
15182{
15183 my $Str = $_[0];
15184 if(not $Str) {
15185 return $Str;
15186 }
15187
15188 $Str=~s/&amp;/&/g;
15189 $Str=~s/&lt;/</g;
15190 $Str=~s/&gt;/>/g;
15191
15192 $Str=~s/&quot;/"/g;
15193 $Str=~s/&#39;/'/g;
15194
15195 return $Str;
15196}
15197
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015198sub black_name($)
15199{
15200 my $Name = $_[0];
15201 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15202}
15203
15204sub highLight_Signature($)
15205{
15206 my $Signature = $_[0];
15207 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15208}
15209
15210sub highLight_Signature_Italic_Color($)
15211{
15212 my $Signature = $_[0];
15213 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15214}
15215
15216sub separate_symbol($)
15217{
15218 my $Symbol = $_[0];
15219 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15220 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15221 ($Name, $Spec, $Ver) = ($1, $2, $3);
15222 }
15223 return ($Name, $Spec, $Ver);
15224}
15225
15226sub cut_f_attrs($)
15227{
15228 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15229 return $2;
15230 }
15231 return "";
15232}
15233
15234sub highLight_Signature_PPos_Italic($$$$$)
15235{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015236 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15237 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015238 if($CheckObjectsOnly) {
15239 $ItalicParams=$ColorParams=0;
15240 }
15241 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15242 my $Return = "";
15243 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15244 $Return = $2;
15245 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015246 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015247 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015248 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015249 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015250 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015251 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015252 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015253 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015254 }
15255 return $Signature;
15256 }
15257 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15258 $Begin.=" " if($Begin!~/ \Z/);
15259 $End = cut_f_attrs($Signature);
15260 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015261 my ($Short, $Params) = split_Signature($Signature);
15262 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015263 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015264 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015265 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015266 $Part=~s/\A\s+|\s+\Z//g;
15267 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15268 if($Part=~/\([\*]+(\w+)\)/i) {
15269 $ParamName = $1;#func-ptr
15270 }
15271 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15272 $ParamName = $1;
15273 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015274 if(not $ParamName)
15275 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015276 push(@Parts, $Part_Styled);
15277 next;
15278 }
15279 if($ItalicParams and not $TName_Tid{1}{$Part}
15280 and not $TName_Tid{2}{$Part})
15281 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015282 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015283 if($Param_Pos ne ""
15284 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015285 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015286 }
15287 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015288 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015289 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015290 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015291 }
15292 $Part_Styled=~s/,(\w)/, $1/g;
15293 push(@Parts, $Part_Styled);
15294 }
15295 if(@Parts)
15296 {
15297 foreach my $Num (0 .. $#Parts)
15298 {
15299 if($Num==$#Parts)
15300 { # add ")" to the last parameter
15301 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15302 }
15303 elsif(length($Parts[$Num])<=45) {
15304 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15305 }
15306 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015307 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015308 }
15309 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015310 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015311 }
15312 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015313 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015314 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015315 $Signature=~s!\[\]![&#160;]!g;
15316 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015317 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15318 if($SymbolVersion) {
15319 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15320 }
15321 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015322}
15323
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015324sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015325{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015326 my $Signature = $_[0];
15327 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15328 {
15329 $Signature=~s/\A\Q$ShortName\E\(//g;
15330 cut_f_attrs($Signature);
15331 $Signature=~s/\)\Z//;
15332 return ($ShortName, $Signature);
15333 }
15334
15335 # error
15336 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015337}
15338
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015339sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015340{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015341 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015342 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015343 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15344 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015345 foreach my $Pos (0 .. length($Params) - 1)
15346 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015347 my $S = substr($Params, $Pos, 1);
15348 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015349 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015350 }
15351 if($S eq "," and
15352 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015353 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015354 if($Comma)
15355 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015356 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015357 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015358 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015359 }
15360 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015361 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015362 }
15363 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015364 if(not $Sp)
15365 { # remove spaces
15366 foreach (@Parts)
15367 {
15368 s/\A //g;
15369 s/ \Z//g;
15370 }
15371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015372 return @Parts;
15373}
15374
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015375sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015376{
15377 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015378 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015379 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015380 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15381 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015382 $Center+=length($1);
15383 }
15384 foreach my $Pos (0 .. length($Sign)-1)
15385 {
15386 my $S = substr($Sign, $Pos, 1);
15387 if($S eq $Target)
15388 {
15389 if($B{"("}==$B{")"}
15390 and $B{"<"}==$B{">"}) {
15391 return $Center;
15392 }
15393 }
15394 if(defined $B{$S}) {
15395 $B{$S}+=1;
15396 }
15397 $Center+=1;
15398 }
15399 return 0;
15400}
15401
15402sub appendFile($$)
15403{
15404 my ($Path, $Content) = @_;
15405 return if(not $Path);
15406 if(my $Dir = get_dirname($Path)) {
15407 mkpath($Dir);
15408 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015409 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015410 print FILE $Content;
15411 close(FILE);
15412}
15413
15414sub writeFile($$)
15415{
15416 my ($Path, $Content) = @_;
15417 return if(not $Path);
15418 if(my $Dir = get_dirname($Path)) {
15419 mkpath($Dir);
15420 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015421 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015422 print FILE $Content;
15423 close(FILE);
15424}
15425
15426sub readFile($)
15427{
15428 my $Path = $_[0];
15429 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015430 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015431 local $/ = undef;
15432 my $Content = <FILE>;
15433 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015434 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015435 $Content=~s/\r/\n/g;
15436 }
15437 return $Content;
15438}
15439
15440sub get_filename($)
15441{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015442 if(defined $Cache{"get_filename"}{$_[0]}) {
15443 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015444 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015445 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15446 return ($Cache{"get_filename"}{$_[0]}=$1);
15447 }
15448 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015449}
15450
15451sub get_dirname($)
15452{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015453 if(defined $Cache{"get_dirname"}{$_[0]}) {
15454 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015455 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015456 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15457 return ($Cache{"get_dirname"}{$_[0]}=$1);
15458 }
15459 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015460}
15461
15462sub separate_path($) {
15463 return (get_dirname($_[0]), get_filename($_[0]));
15464}
15465
15466sub esc($)
15467{
15468 my $Str = $_[0];
15469 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15470 return $Str;
15471}
15472
15473sub readLineNum($$)
15474{
15475 my ($Path, $Num) = @_;
15476 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015477 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015478 foreach (1 ... $Num) {
15479 <FILE>;
15480 }
15481 my $Line = <FILE>;
15482 close(FILE);
15483 return $Line;
15484}
15485
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015486sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015487{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015488 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015489 return () if(not $Path or not -f $Path);
15490 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015491 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15492 {
15493 foreach my $AttrVal (split(/;/, $1))
15494 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015495 if($AttrVal=~/(.+):(.+)/)
15496 {
15497 my ($Name, $Value) = ($1, $2);
15498 $Attributes{$Name} = $Value;
15499 }
15500 }
15501 }
15502 return \%Attributes;
15503}
15504
15505sub is_abs($) {
15506 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15507}
15508
15509sub get_abs_path($)
15510{ # abs_path() should NOT be called for absolute inputs
15511 # because it can change them
15512 my $Path = $_[0];
15513 if(not is_abs($Path)) {
15514 $Path = abs_path($Path);
15515 }
15516 return $Path;
15517}
15518
15519sub get_OSgroup()
15520{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015521 my $N = $Config{"osname"};
15522 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015523 return "macos";
15524 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015525 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015526 return "bsd";
15527 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015528 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015529 return "beos";
15530 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015531 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015532 return "symbian";
15533 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015534 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015535 return "windows";
15536 }
15537 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015538 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015539 }
15540}
15541
15542sub getGccVersion($)
15543{
15544 my $LibVersion = $_[0];
15545 if($GCC_VERSION{$LibVersion})
15546 { # dump version
15547 return $GCC_VERSION{$LibVersion};
15548 }
15549 elsif($UsedDump{$LibVersion}{"V"})
15550 { # old-version dumps
15551 return "unknown";
15552 }
15553 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15554 if(not $GccVersion) {
15555 return "unknown";
15556 }
15557 return $GccVersion;
15558}
15559
15560sub showArch($)
15561{
15562 my $Arch = $_[0];
15563 if($Arch eq "arm"
15564 or $Arch eq "mips") {
15565 return uc($Arch);
15566 }
15567 return $Arch;
15568}
15569
15570sub getArch($)
15571{
15572 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015573
15574 if($TargetArch) {
15575 return $TargetArch;
15576 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015577 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015578 { # dump version
15579 return $CPU_ARCH{$LibVersion};
15580 }
15581 elsif($UsedDump{$LibVersion}{"V"})
15582 { # old-version dumps
15583 return "unknown";
15584 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015585
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015586 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015587}
15588
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015589sub get_Report_Header($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015590{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015591 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015592 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015593 if(getArch(1) ne getArch(2)
15594 or getArch(1) eq "unknown"
15595 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015596 { # don't show architecture in the header
15597 $ArchInfo="";
15598 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015599 my $Report_Header = "<h1><span class='nowrap'>";
15600 if($Level eq "Source") {
15601 $Report_Header .= "Source compatibility";
15602 }
15603 elsif($Level eq "Binary") {
15604 $Report_Header .= "Binary compatibility";
15605 }
15606 else {
15607 $Report_Header .= "API compatibility";
15608 }
15609 $Report_Header .= " report for the <span style='color:Blue;'>$TargetLibraryFName</span> $TargetComponent</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015610 $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>";
15611 if($AppPath) {
15612 $Report_Header .= " <span class='nowrap'>&#160;(relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)</span>";
15613 }
15614 $Report_Header .= "</h1>\n";
15615 return $Report_Header;
15616}
15617
15618sub get_SourceInfo()
15619{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015620 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015621 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015622 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015623 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015624 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015625 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15626 $CheckedHeaders .= "<div class='h_list'>\n";
15627 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15628 {
15629 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15630 my $Name = get_filename($Identity);
15631 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15632 $CheckedHeaders .= $Name.$Comment."<br/>\n";
15633 }
15634 $CheckedHeaders .= "</div>\n";
15635 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015636 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015637
15638 if(my @Sources = keys(%{$Registered_Sources{1}}))
15639 {
15640 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15641 $CheckedSources .= "<div class='h_list'>\n";
15642 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15643 {
15644 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15645 my $Name = get_filename($Identity);
15646 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15647 $CheckedSources .= $Name.$Comment."<br/>\n";
15648 }
15649 $CheckedSources .= "</div>\n";
15650 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015652 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015653 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015654 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015655 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015656 $CheckedLibs .= "<div class='lib_list'>\n";
15657 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15658 {
15659 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15660 $CheckedLibs .= $Library."<br/>\n";
15661 }
15662 $CheckedLibs .= "</div>\n";
15663 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015664 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015665 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15666}
15667
15668sub get_ObjTitle()
15669{
15670 if(defined $UsedDump{1}{"DWARF"}) {
15671 return "Objects";
15672 }
15673 else {
15674 return ucfirst($SLIB_TYPE)." Libraries";
15675 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015676}
15677
15678sub get_TypeProblems_Count($$$)
15679{
15680 my ($TypeChanges, $TargetPriority, $Level) = @_;
15681 my $Type_Problems_Count = 0;
15682 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15683 {
15684 my %Kinds_Target = ();
15685 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15686 {
15687 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15688 {
15689 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015690 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15691 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015692 if($Kinds_Target{$Kind}{$Target}) {
15693 next;
15694 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015695
15696 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15697 {
15698 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15699 { # select a problem with the highest priority
15700 next;
15701 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015702 }
15703 $Kinds_Target{$Kind}{$Target} = 1;
15704 $Type_Problems_Count += 1;
15705 }
15706 }
15707 }
15708 return $Type_Problems_Count;
15709}
15710
15711sub get_Summary($)
15712{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015713 my $Level = $_[0];
15714 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015715 $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 +040015716 %{$RESULT{$Level}} = (
15717 "Problems"=>0,
15718 "Warnings"=>0,
15719 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015720 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015721 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015722 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015723 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015724 {
15725 if(not defined $CompatRules{$Level}{$Kind})
15726 { # unknown rule
15727 if(not $UnknownRules{$Level}{$Kind})
15728 { # only one warning
15729 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15730 $UnknownRules{$Level}{$Kind}=1;
15731 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015732 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015733 }
15734 }
15735 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015736 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15737 {
15738 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15739 {
15740 if(not defined $CompatRules{$Level}{$Kind})
15741 { # unknown rule
15742 if(not $UnknownRules{$Level}{$Kind})
15743 { # only one warning
15744 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15745 $UnknownRules{$Level}{$Kind}=1;
15746 }
15747 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15748 }
15749 }
15750 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015751 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015752 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015753 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015754 {
15755 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15756 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015757 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015758 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015759 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015760 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015761 $Added += 1;
15762 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015763 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015764 {
15765 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015766 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015767 }
15768 else
15769 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015770 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015771 $I_Other += 1;
15772 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015773 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015774 $I_Problems_High += 1;
15775 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015776 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015777 $I_Problems_Medium += 1;
15778 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015779 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015780 $I_Problems_Low += 1;
15781 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015782 if(($Severity ne "Low" or $StrictCompat)
15783 and $Severity ne "Safe") {
15784 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015785 }
15786 }
15787 }
15788 }
15789 }
15790 }
15791 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015792 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015793 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015794 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015795 {
15796 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15797 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015798 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015799 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015800 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15801 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015802 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015803 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15804
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015805 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015806 { # select a problem with the highest priority
15807 next;
15808 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015809
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015810 if(($Severity ne "Low" or $StrictCompat)
15811 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015812 {
15813 if(defined $TotalAffected{$Level}{$Interface})
15814 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015815 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15816 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015817 }
15818 }
15819 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015820 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015822 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015823
15824 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15825
15826 if($MaxSeverity)
15827 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015828 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15829 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015830 }
15831 }
15832 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015833 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015834 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015835 }
15836 }
15837 }
15838 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015839
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015840 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15841 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15842 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15843 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015844
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015845 %TypeChanges = (); # free memory
15846
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015847 if($CheckObjectsOnly)
15848 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015849 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015850 }
15851 else
15852 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015853 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015854 if($ExtendedCheck)
15855 { # don't count external_func_0 for constants
15856 $SCount-=1;
15857 }
15858 if($SCount)
15859 {
15860 my %Weight = (
15861 "High" => 100,
15862 "Medium" => 50,
15863 "Low" => 25
15864 );
15865 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015866 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015867 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015868 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015869 }
15870 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015871 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015872 }
15873 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015874 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15875 if($RESULT{$Level}{"Affected"}>=100) {
15876 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015877 }
15878
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015879 $RESULT{$Level}{"Problems"} += $Removed;
15880 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015881 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015882 if($StrictCompat) {
15883 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15884 }
15885 else {
15886 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015888
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015889 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015890 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015891 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015892 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015893 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015894 if($Severity eq "Safe")
15895 {
15896 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015897 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015898 elsif($Severity eq "Low")
15899 {
15900 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015901 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015902 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015903 }
15904
15905 if($C_Problems_Low)
15906 {
15907 if($StrictCompat) {
15908 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15909 }
15910 else {
15911 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015912 }
15913 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015914 if($CheckImpl and $Level eq "Binary")
15915 {
15916 if($StrictCompat) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015917 $RESULT{$Level}{"Problems"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015918 }
15919 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015920 $RESULT{$Level}{"Warnings"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015921 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015922 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015923 if($RESULT{$Level}{"Problems"}
15924 and $RESULT{$Level}{"Affected"}) {
15925 $RESULT{$Level}{"Verdict"} = "incompatible";
15926 }
15927 else {
15928 $RESULT{$Level}{"Verdict"} = "compatible";
15929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015930
15931 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15932 if(not $TotalTypes)
15933 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015934 $TotalTypes = keys(%{$TName_Tid{1}});
15935 }
15936
15937 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15938 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15939
15940 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15941
15942 if($ReportFormat eq "xml")
15943 { # XML
15944 # test info
15945 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15946 $TestInfo .= " <version1>\n";
15947 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015948 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015949 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15950 $TestInfo .= " </version1>\n";
15951
15952 $TestInfo .= " <version2>\n";
15953 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015954 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015955 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15956 $TestInfo .= " </version2>\n";
15957 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15958
15959 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015960 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015961 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015962 $TestResults .= " <headers>\n";
15963 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15964 {
15965 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15966 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15967 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15968 }
15969 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015970 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015971
15972 if(my @Sources = keys(%{$Registered_Sources{1}}))
15973 {
15974 $TestResults .= " <sources>\n";
15975 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15976 {
15977 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15978 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15979 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15980 }
15981 $TestResults .= " </sources>\n";
15982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015983
15984 $TestResults .= " <libs>\n";
15985 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15986 {
15987 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15988 $TestResults .= " <name>$Library</name>\n";
15989 }
15990 $TestResults .= " </libs>\n";
15991
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015992 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015993 $TestResults .= " <types>".$TotalTypes."</types>\n";
15994
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015995 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15996 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015997 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15998
15999 # problem summary
16000 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
16001 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
16002
16003 $Problem_Summary .= " <problems_with_types>\n";
16004 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
16005 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
16006 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
16007 $Problem_Summary .= " <safe>$T_Other</safe>\n";
16008 $Problem_Summary .= " </problems_with_types>\n";
16009
16010 $Problem_Summary .= " <problems_with_symbols>\n";
16011 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
16012 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
16013 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016014 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016015 $Problem_Summary .= " </problems_with_symbols>\n";
16016
16017 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016018 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016019 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016020 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016021 {
16022 $Problem_Summary .= " <impl>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016023 $Problem_Summary .= " <low>".keys(%CompatProblems_Impl)."</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016024 $Problem_Summary .= " </impl>\n";
16025 }
16026 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
16027
16028 return ($TestInfo.$TestResults.$Problem_Summary, "");
16029 }
16030 else
16031 { # HTML
16032 # test info
16033 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016034 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016035 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetLibraryFName</td></tr>\n";
16036
16037 my (@VInf1, @VInf2, $AddTestInfo) = ();
16038 if($Arch1 ne "unknown"
16039 and $Arch2 ne "unknown")
16040 { # CPU arch
16041 if($Arch1 eq $Arch2)
16042 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016043 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016044 }
16045 else
16046 { # go to the version number
16047 push(@VInf1, showArch($Arch1));
16048 push(@VInf2, showArch($Arch2));
16049 }
16050 }
16051 if($GccV1 ne "unknown"
16052 and $GccV2 ne "unknown"
16053 and $OStarget ne "windows")
16054 { # GCC version
16055 if($GccV1 eq $GccV2)
16056 { # go to the separate section
16057 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16058 }
16059 else
16060 { # go to the version number
16061 push(@VInf1, "gcc ".$GccV1);
16062 push(@VInf2, "gcc ".$GccV2);
16063 }
16064 }
16065 # show long version names with GCC version and CPU architecture name (if different)
16066 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16067 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16068 $TestInfo .= $AddTestInfo;
16069 #if($COMMON_LANGUAGE{1}) {
16070 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16071 #}
16072 if($ExtendedCheck) {
16073 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16074 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016075 if($JoinReport)
16076 {
16077 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016078 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016079 }
16080 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016081 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016082 }
16083 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016084 $TestInfo .= "</table>\n";
16085
16086 # test results
16087 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016088 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016089
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016090 if(my @Headers = keys(%{$Registered_Headers{1}}))
16091 {
16092 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16093 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16094 }
16095 elsif($CheckObjectsOnly) {
16096 $TestResults .= "<tr><th>Total Header Files</th><td>0&#160;(not&#160;analyzed)</td></tr>\n";
16097 }
16098
16099 if(my @Sources = keys(%{$Registered_Sources{1}}))
16100 {
16101 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16102 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16103 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016104
16105 if(not $ExtendedCheck)
16106 {
16107 my $Libs_Link = "0";
16108 $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 +040016109 $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 +040016110 }
16111
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016112 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016113
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016114 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016115 if($JoinReport) {
16116 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16117 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016118 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016119 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016120 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
16121 }
16122 else {
16123 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
16124 }
16125 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016126 $TestResults .= "</table>\n";
16127
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016128 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016129 # problem summary
16130 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016131 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016132 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16133
16134 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016135 if($Added>0)
16136 {
16137 if($JoinReport) {
16138 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16139 }
16140 else {
16141 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16142 }
16143 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016144 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016145 $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 +040016146
16147 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016148 if($Removed>0)
16149 {
16150 if($JoinReport) {
16151 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16152 }
16153 else {
16154 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16155 }
16156 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016157 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016158 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
16159 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016160
16161 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016162 $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 +040016163 $TH_Link = "n/a" if($CheckObjectsOnly);
16164 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016165 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
16166 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016167
16168 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016169 $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 +040016170 $TM_Link = "n/a" if($CheckObjectsOnly);
16171 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016172 $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 +040016173
16174 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016175 $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 +040016176 $TL_Link = "n/a" if($CheckObjectsOnly);
16177 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016178 $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 +040016179
16180 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016181 $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 +040016182 $IH_Link = "n/a" if($CheckObjectsOnly);
16183 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016184 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
16185 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016186
16187 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016188 $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 +040016189 $IM_Link = "n/a" if($CheckObjectsOnly);
16190 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016191 $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 +040016192
16193 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016194 $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 +040016195 $IL_Link = "n/a" if($CheckObjectsOnly);
16196 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016197 $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 +040016198
16199 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016200 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16201 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016202 }
16203 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016204 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016205 $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 +040016206
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016207 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016208 {
16209 my $ChangedImpl_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016210 $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 +040016211 $ChangedImpl_Link = "n/a" if($CheckHeadersOnly);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016212 $META_DATA .= "changed_implementation:".keys(%CompatProblems_Impl).";";
16213 $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 +040016214 }
16215 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016216 if($T_Other and not $CheckObjectsOnly)
16217 {
16218 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016219 $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 +040016220 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016221
16222 if($I_Other and not $CheckObjectsOnly)
16223 {
16224 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016225 $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 +040016226 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016227
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016228 if($C_Other and not $CheckObjectsOnly)
16229 {
16230 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16231 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
16232 }
16233
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016234 $META_DATA .= "tool_version:$TOOL_VERSION";
16235 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016236 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016237 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16238 }
16239}
16240
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016241sub getStyle($$$)
16242{
16243 my ($Subj, $Act, $Num) = @_;
16244 my %Style = (
16245 "A"=>"new",
16246 "R"=>"failed",
16247 "S"=>"passed",
16248 "L"=>"warning",
16249 "M"=>"failed",
16250 "H"=>"failed"
16251 );
16252 if($Num>0) {
16253 return " class='".$Style{$Act}."'";
16254 }
16255 return "";
16256}
16257
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016258sub show_number($)
16259{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016260 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016261 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016262 my $Num = cut_off_number($_[0], 2, 0);
16263 if($Num eq "0")
16264 {
16265 foreach my $P (3 .. 7)
16266 {
16267 $Num = cut_off_number($_[0], $P, 1);
16268 if($Num ne "0") {
16269 last;
16270 }
16271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016272 }
16273 if($Num eq "0") {
16274 $Num = $_[0];
16275 }
16276 return $Num;
16277 }
16278 return $_[0];
16279}
16280
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016281sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016282{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016283 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016284 if($num!~/\./)
16285 {
16286 $num .= ".";
16287 foreach (1 .. $digs_to_cut-1) {
16288 $num .= "0";
16289 }
16290 }
16291 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16292 {
16293 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16294 $num .= "0";
16295 }
16296 }
16297 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16298 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16299 }
16300 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016301 if($z) {
16302 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16303 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016304 return $num;
16305}
16306
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016307sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016308{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016309 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016310 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016311
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016312 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016313 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16314 {
16315 my $Header = $Constants{1}{$Constant}{"Header"};
16316 if(not $Header)
16317 { # added
16318 $Header = $Constants{2}{$Constant}{"Header"}
16319 }
16320
16321 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16322 {
16323 if(not defined $CompatRules{$Level}{$Kind}) {
16324 next;
16325 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016326 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016327 next;
16328 }
16329 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16330 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016331 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016332
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016333 if($ReportFormat eq "xml")
16334 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016335 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016336 {
16337 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016338 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016339 {
16340 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016341 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16342 {
16343 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16344 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16345 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016346
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016347 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16348 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16349 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016350 if($Overcome) {
16351 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16352 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016353 $CHANGED_CONSTANTS .= " </problem>\n";
16354 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016355 $CHANGED_CONSTANTS .= " </constant>\n";
16356 }
16357 $CHANGED_CONSTANTS .= " </header>\n";
16358 }
16359 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16360 }
16361 else
16362 { # HTML
16363 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016364 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016365 {
16366 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016367 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016368 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016369 my $Report = "";
16370
16371 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16372 {
16373 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16374 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16375 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16376 $Number += 1;
16377 }
16378 if($Report)
16379 {
16380 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16381 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16382 $Report = insertIDs($Report);
16383 }
16384 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016385 }
16386 $CHANGED_CONSTANTS .= "<br/>\n";
16387 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016388 if($CHANGED_CONSTANTS)
16389 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016390 my $Title = "Problems with Constants, $TargetSeverity Severity";
16391 if($TargetSeverity eq "Safe")
16392 { # Safe Changes
16393 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016394 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016395 $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 +040016396 }
16397 }
16398 return $CHANGED_CONSTANTS;
16399}
16400
16401sub get_Report_Impl()
16402{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016403 my $CHANGED_IMPLEMENTATION = "";
16404 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016405 foreach my $Interface (sort keys(%CompatProblems_Impl))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016406 {
16407 my $HeaderName = $CompleteSignature{1}{$Interface}{"Header"};
16408 my $DyLib = $Symbol_Library{1}{$Interface};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016409 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016410 }
16411 my $Changed_Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016412 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016413 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016414 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016415 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016416 my %NameSpaceSymbols = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016417 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016418 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016419 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016420 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016421 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016422 $CHANGED_IMPLEMENTATION .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016423 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016424 foreach my $Interface (@SortedInterfaces)
16425 {
16426 $Changed_Number += 1;
16427 my $Signature = get_Signature($Interface, 1);
16428 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016429 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016430 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016431 $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 +040016432 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016433 $CHANGED_IMPLEMENTATION .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016435 }
16436 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016437 if($CHANGED_IMPLEMENTATION)
16438 {
16439 $CHANGED_IMPLEMENTATION = insertIDs($CHANGED_IMPLEMENTATION);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016440 $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 +040016441 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016442
16443 # clean memory
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016444 %CompatProblems_Impl = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016445
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016446 return $CHANGED_IMPLEMENTATION;
16447}
16448
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016449sub getTitle($$$)
16450{
16451 my ($Header, $Library, $NameSpace) = @_;
16452 my $Title = "";
16453 if($Library and $Library!~/\.\w+\Z/) {
16454 $Library .= " (.$LIB_EXT)";
16455 }
16456 if($Header and $Library)
16457 {
16458 $Title .= "<span class='h_name'>$Header</span>";
16459 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16460 }
16461 elsif($Library) {
16462 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16463 }
16464 elsif($Header) {
16465 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16466 }
16467 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016468 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016469 }
16470 return $Title;
16471}
16472
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016473sub get_Report_Added($)
16474{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016475 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016476 my $ADDED_INTERFACES = "";
16477 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016478 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016479 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016480 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016481 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016482 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016483 {
16484 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16485 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016486 if($Level eq "Source" and $ReportFormat eq "html")
16487 { # do not show library name in HTML report
16488 $DyLib = "";
16489 }
16490 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016491 }
16492 }
16493 }
16494 if($ReportFormat eq "xml")
16495 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016496 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016497 {
16498 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016499 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016500 {
16501 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016502 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016503 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16504 }
16505 $ADDED_INTERFACES .= " </library>\n";
16506 }
16507 $ADDED_INTERFACES .= " </header>\n";
16508 }
16509 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16510 }
16511 else
16512 { # HTML
16513 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016514 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016515 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016516 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016517 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016518 my %NameSpaceSymbols = ();
16519 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016520 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016521 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016522 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016523 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016524 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16525 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016526 foreach my $Interface (@SortedInterfaces)
16527 {
16528 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016529 my $Signature = get_Signature($Interface, 2);
16530 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016531 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016532 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016533 if($Interface=~/\A(_Z|\?)/)
16534 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016535 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016536 $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 +040016537 }
16538 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016539 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016540 }
16541 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016542 else
16543 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016544 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016545 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016546 }
16547 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016548 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016549 }
16550 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016551 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016552 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016553 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016554 }
16555 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016556 if($ADDED_INTERFACES)
16557 {
16558 my $Anchor = "<a name='Added'></a>";
16559 if($JoinReport) {
16560 $Anchor = "<a name='".$Level."_Added'></a>";
16561 }
16562 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016563 }
16564 }
16565 return $ADDED_INTERFACES;
16566}
16567
16568sub get_Report_Removed($)
16569{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016570 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016571 my $REMOVED_INTERFACES = "";
16572 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016573 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016574 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016575 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016576 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016577 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016578 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016579 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16580 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016581 if($Level eq "Source" and $ReportFormat eq "html")
16582 { # do not show library name in HTML report
16583 $DyLib = "";
16584 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016585 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016586 }
16587 }
16588 }
16589 if($ReportFormat eq "xml")
16590 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016591 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016592 {
16593 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016594 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016595 {
16596 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016597 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16598 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016599 }
16600 $REMOVED_INTERFACES .= " </library>\n";
16601 }
16602 $REMOVED_INTERFACES .= " </header>\n";
16603 }
16604 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16605 }
16606 else
16607 { # HTML
16608 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016609 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016610 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016611 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016612 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016613 my %NameSpaceSymbols = ();
16614 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016615 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016616 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016617 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016618 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016619 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16620 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016621 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016622 {
16623 $Removed_Number += 1;
16624 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016625 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016626 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016627 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016628 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016629 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016630 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016631 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016632 $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 +040016633 }
16634 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016635 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016636 }
16637 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016638 else
16639 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016640 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016641 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016642 }
16643 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016644 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016645 }
16646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016647 }
16648 }
16649 $REMOVED_INTERFACES .= "<br/>\n";
16650 }
16651 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016652 if($REMOVED_INTERFACES)
16653 {
16654 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16655 if($JoinReport) {
16656 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16657 }
16658 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016659 }
16660 }
16661 return $REMOVED_INTERFACES;
16662}
16663
16664sub getXmlParams($$)
16665{
16666 my ($Content, $Problem) = @_;
16667 return "" if(not $Content or not $Problem);
16668 my %XMLparams = ();
16669 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16670 {
16671 my $Macro = "\@".lc($Attr);
16672 if($Content=~/\Q$Macro\E/) {
16673 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16674 }
16675 }
16676 my @PString = ();
16677 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016678 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016679 }
16680 if(@PString) {
16681 return " ".join(" ", @PString);
16682 }
16683 else {
16684 return "";
16685 }
16686}
16687
16688sub addMarkup($)
16689{
16690 my $Content = $_[0];
16691 # auto-markup
16692 $Content=~s/\n[ ]*//; # spaces
16693 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16694 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016695 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016696 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16697 if($Content=~/\ANOTE:/)
16698 { # notes
16699 $Content=~s!(NOTE):!<b>$1</b>:!g;
16700 }
16701 else {
16702 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16703 }
16704 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16705 my @Keywords = (
16706 "void",
16707 "const",
16708 "static",
16709 "restrict",
16710 "volatile",
16711 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016712 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016713 );
16714 my $MKeys = join("|", @Keywords);
16715 foreach (@Keywords) {
16716 $MKeys .= "|non-".$_;
16717 }
16718 $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 +040016719
16720 # Markdown
16721 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16722 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016723 return $Content;
16724}
16725
16726sub applyMacroses($$$$)
16727{
16728 my ($Level, $Kind, $Content, $Problem) = @_;
16729 return "" if(not $Content or not $Problem);
16730 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16731 $Content = addMarkup($Content);
16732 # macros
16733 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16734 {
16735 my $Macro = "\@".lc($Attr);
16736 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016737 if(not defined $Value
16738 or $Value eq "") {
16739 next;
16740 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016741 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016742 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016743 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
16744 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016745 $Value = black_name($Value);
16746 }
16747 elsif($Value=~/\s/) {
16748 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16749 }
16750 elsif($Value=~/\A\d+\Z/
16751 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16752 { # bits to bytes
16753 if($Value % $BYTE_SIZE)
16754 { # bits
16755 if($Value==1) {
16756 $Value = "<b>".$Value."</b> bit";
16757 }
16758 else {
16759 $Value = "<b>".$Value."</b> bits";
16760 }
16761 }
16762 else
16763 { # bytes
16764 $Value /= $BYTE_SIZE;
16765 if($Value==1) {
16766 $Value = "<b>".$Value."</b> byte";
16767 }
16768 else {
16769 $Value = "<b>".$Value."</b> bytes";
16770 }
16771 }
16772 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016773 else
16774 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016775 $Value = "<b>".htmlSpecChars($Value)."</b>";
16776 }
16777 $Content=~s/\Q$Macro\E/$Value/g;
16778 }
16779
16780 if($Content=~/(\A|[^\@\w])\@\w/)
16781 {
16782 if(not $IncompleteRules{$Level}{$Kind})
16783 { # only one warning
16784 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16785 $IncompleteRules{$Level}{$Kind} = 1;
16786 }
16787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016788 return $Content;
16789}
16790
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016791sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016792{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016793 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016794 my $INTERFACE_PROBLEMS = "";
16795 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016796
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016797 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016798 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016799 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16800 if($SV and defined $CompatProblems{$Level}{$SN}) {
16801 next;
16802 }
16803 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016804 {
16805 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016806 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016807 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016808 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16809 my $DyLib = $Symbol_Library{1}{$Symbol};
16810 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016811 { # Symbol with Version
16812 $DyLib = $Symbol_Library{1}{$VSym};
16813 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016814 if(not $DyLib)
16815 { # const global data
16816 $DyLib = "";
16817 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016818 if($Level eq "Source" and $ReportFormat eq "html")
16819 { # do not show library name in HTML report
16820 $DyLib = "";
16821 }
16822 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16823 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016824 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016825 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16826 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016827 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016828 }
16829 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016830 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16831 {
16832 delete($SymbolChanges{$Symbol}{$Kind});
16833 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016834 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016835 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016836 }
16837 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016838 if(not keys(%{$SymbolChanges{$Symbol}})) {
16839 delete($SymbolChanges{$Symbol});
16840 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016841 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016842
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016843 if($ReportFormat eq "xml")
16844 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016845 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016846 {
16847 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016848 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016849 {
16850 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016851 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16852 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016853 {
16854 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16855 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16856 {
16857 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16858 {
16859 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016860 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016861
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016862 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16863 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16864 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16865 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16866 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016867 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16868 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16869 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016870 $INTERFACE_PROBLEMS .= " </problem>\n";
16871 }
16872 }
16873 $INTERFACE_PROBLEMS .= " </symbol>\n";
16874 }
16875 $INTERFACE_PROBLEMS .= " </library>\n";
16876 }
16877 $INTERFACE_PROBLEMS .= " </header>\n";
16878 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016879 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016880 }
16881 else
16882 { # HTML
16883 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016884 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016885 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016886 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016887 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016888 my (%NameSpaceSymbols, %NewSignature) = ();
16889 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016890 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016891 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016892 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016893 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016894 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016895 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 +040016896 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016897 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016898 my $Signature = get_Signature($Symbol, 1);
16899 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016900 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016901 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016902 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016903 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016904 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016905 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016906 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016907 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016908 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016909 }
16910 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16911 {
16912 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016913 $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 +040016914 $ProblemNum += 1;
16915 $ProblemsNum += 1;
16916 }
16917 }
16918 }
16919 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016920 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016921 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016922 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016923 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016924 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016925 }
16926 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016927 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016928 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016929 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16930 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16931 if($NewSignature{$Symbol})
16932 { # argument list changed to
16933 $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 +040016934 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016935 if($Symbol=~/\A(_Z|\?)/) {
16936 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16937 }
16938 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16939 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016940 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016941 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016942 }
16943 }
16944 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016945 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016946 }
16947 }
16948 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016949
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016950 if($INTERFACE_PROBLEMS)
16951 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016952 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16953 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16954 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016955 { # Safe Changes
16956 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016957 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016958 $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 +040016959 }
16960 }
16961 return $INTERFACE_PROBLEMS;
16962}
16963
16964sub get_Report_TypeProblems($$)
16965{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016966 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016967 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016968 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016969
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016970 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016971 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016972 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016973 {
16974 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16975 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016976 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016977 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016978 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016979 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016980 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016981
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016982 if($Severity eq "Safe"
16983 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016984 next;
16985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016986
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016987 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16988 {
16989 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16990 { # select a problem with the highest priority
16991 next;
16992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016993 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016994
16995 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016996 }
16997 }
16998 }
16999 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017000
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017001 my %Kinds_Locations = ();
17002 foreach my $TypeName (keys(%TypeChanges))
17003 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017004 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017005 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
17006 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017007 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017008 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017009 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017010 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017011 { # other priority
17012 delete($TypeChanges{$TypeName}{$Kind}{$Location});
17013 next;
17014 }
17015 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
17016 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017017 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017018 { # duplicate target
17019 delete($TypeChanges{$TypeName}{$Kind}{$Location});
17020 next;
17021 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017022 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017023 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017024 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017025 }
17026 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
17027 delete($TypeChanges{$TypeName}{$Kind});
17028 }
17029 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017030 if(not keys(%{$TypeChanges{$TypeName}})) {
17031 delete($TypeChanges{$TypeName});
17032 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017033 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017034
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017035 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 +040017036 if($ReportFormat eq "xml")
17037 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017038 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017039 {
17040 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017041 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017042 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017043 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017044 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
17045 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017046 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017047 {
17048 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
17049 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
17050 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
17051 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
17052 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
17053 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017054 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
17055 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
17056 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017057 $TYPE_PROBLEMS .= " </problem>\n";
17058 }
17059 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017060 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017061 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017062 $TYPE_PROBLEMS .= showVTables($TypeName);
17063 }
17064 $TYPE_PROBLEMS .= " </type>\n";
17065 }
17066 $TYPE_PROBLEMS .= " </header>\n";
17067 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017068 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017069 }
17070 else
17071 { # HTML
17072 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017073 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017074 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017075 my (%NameSpace_Type) = ();
17076 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017077 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017078 }
17079 foreach my $NameSpace (sort keys(%NameSpace_Type))
17080 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017081 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017082 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 +040017083 foreach my $TypeName (@SortedTypes)
17084 {
17085 my $ProblemNum = 1;
17086 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017087
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017088 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
17089 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017090 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017091 {
17092 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
17093 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17094 {
17095 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
17096 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
17097 $ProblemNum += 1;
17098 $ProblemsNum += 1;
17099 }
17100 }
17101 }
17102 $ProblemNum -= 1;
17103 if($TYPE_REPORT)
17104 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017105 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017106 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017107 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017108 $ShowVTables = showVTables($TypeName);
17109 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017110
17111 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017112 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17113 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17114 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17115 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017116 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017117 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017118 }
17119 }
17120 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017121 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017122 }
17123 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017124
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017125 if($TYPE_PROBLEMS)
17126 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017127 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17128 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017129 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017130 { # Safe Changes
17131 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017132 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017133 $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 +040017134 }
17135 }
17136 return $TYPE_PROBLEMS;
17137}
17138
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017139sub show_Type($$$)
17140{
17141 my ($Name, $Html, $LibVersion) = @_;
17142 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17143 $TType = lc($TType);
17144 if($TType=~/struct|union|enum/) {
17145 $Name=~s/\A\Q$TType\E //g;
17146 }
17147 if($Html) {
17148 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17149 }
17150 else {
17151 $Name = $TType." ".$Name;
17152 }
17153 return $Name;
17154}
17155
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017156sub get_Anchor($$$)
17157{
17158 my ($Kind, $Level, $Severity) = @_;
17159 if($JoinReport)
17160 {
17161 if($Severity eq "Safe") {
17162 return "Other_".$Level."_Changes_In_".$Kind."s";
17163 }
17164 else {
17165 return $Kind."_".$Level."_Problems_".$Severity;
17166 }
17167 }
17168 else
17169 {
17170 if($Severity eq "Safe") {
17171 return "Other_Changes_In_".$Kind."s";
17172 }
17173 else {
17174 return $Kind."_Problems_".$Severity;
17175 }
17176 }
17177}
17178
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017179sub showVTables($)
17180{
17181 my $TypeName = $_[0];
17182 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017183 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017184 if(defined $Type1{"VTable"}
17185 and keys(%{$Type1{"VTable"}}))
17186 {
17187 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017188 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017189 if(defined $Type2{"VTable"}
17190 and keys(%{$Type2{"VTable"}}))
17191 {
17192 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17193 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017194 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017195 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017196 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17197 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017198 }
17199 my $VTABLES = "";
17200 if($ReportFormat eq "xml")
17201 { # XML
17202 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017203 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017204 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017205 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017206 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17207 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017208 $VTABLES .= " </entry>\n";
17209 }
17210 $VTABLES .= " </vtable>\n\n";
17211 }
17212 else
17213 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017214 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017215 $VTABLES .= "<tr><th width='2%'>Offset</th>";
17216 $VTABLES .= "<th width='45%'>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
17217 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017218 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017219 {
17220 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017221 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017222 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017223 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017224 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017225 $Color1 = " class='failed'";
17226 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017227 }
17228 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017229 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017230 }
17231 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017232 $VTABLES .= "<tr><th>".$Index."</th>\n";
17233 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17234 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017235 }
17236 $VTABLES .= "</table><br/>\n";
17237 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017238 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017239 }
17240 return $VTABLES;
17241 }
17242 }
17243 return "";
17244}
17245
17246sub simpleVEntry($)
17247{
17248 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017249 if(not defined $VEntry
17250 or $VEntry eq "") {
17251 return "";
17252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017253 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17254 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17255 if($VEntry=~/\A_ZThn.+\Z/) {
17256 $VEntry = "non-virtual thunk";
17257 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017258 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017259 # support for old GCC versions
17260 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17261 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17262 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017263 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17264 return $VEntry;
17265}
17266
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017267sub adjustParamPos($$$)
17268{
17269 my ($Pos, $Symbol, $LibVersion) = @_;
17270 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17271 {
17272 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17273 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17274 {
17275 return $Pos-1;
17276 }
17277
17278 return $Pos;
17279 }
17280
17281 return undef;
17282}
17283
17284sub getParamPos($$$)
17285{
17286 my ($Name, $Symbol, $LibVersion) = @_;
17287
17288 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17289 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17290 {
17291 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17292 foreach (keys(%{$Info->{"Param"}}))
17293 {
17294 if($Info->{"Param"}{$_}{"name"} eq $Name)
17295 {
17296 return $_;
17297 }
17298 }
17299 }
17300
17301 return undef;
17302}
17303
17304sub getParamName($)
17305{
17306 my $Loc = $_[0];
17307 $Loc=~s/\->.*//g;
17308 return $Loc;
17309}
17310
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017311sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017312{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017313 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017314 my $LIMIT = 1000;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017315
17316 if(defined $AffectLimit)
17317 {
17318 $LIMIT = $AffectLimit;
17319 }
17320 else
17321 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017322 if($#{$Syms}>=1999)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017323 { # reduce size of the report
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017324 $AffectLimit = 10;
17325
17326 printMsg("WARNING", "reducing limit of affected symbols shown in the report to $AffectLimit");
17327 $LIMIT = $AffectLimit;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017328 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017329 }
17330 my %SProblems = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017331 LOOP: foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017332 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017333 if(index($Symbol, "_Z")==0
17334 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017335 { # duplicated problems for C2 constructors, D2 and D0 destructors
17336 next;
17337 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017338
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017339 my ($MinPath_Length, $ProblemLocation_Last) = (-1, "");
17340 my $Severity_Max = 0;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017341
17342 foreach my $Kind (keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017343 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017344 if(not defined $CompatProblems{$Level}{$Symbol}
17345 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17346 next;
17347 }
17348
17349 foreach my $Location (keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017350 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017351 if(keys(%SProblems)>$LIMIT) {
17352 last LOOP;
17353 }
17354
17355 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017356 next;
17357 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017358
17359 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17360 if($Level eq "Source")
17361 { # remove symbol version
17362 $Symbol=$SN;
17363 }
17364
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017365 if($SV and defined $CompatProblems{$Level}{$SN}
17366 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Location})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017367 { # duplicated problems for versioned symbols
17368 next;
17369 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017370
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017371 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017372 if($Type_Name ne $Target_TypeName) {
17373 next;
17374 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017375
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017376 my $PName = getParamName($Location);
17377 my $PPos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17378
17379 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017380 my $Path_Length = 0;
17381 my $ProblemLocation = $Location;
17382 if($Type_Name) {
17383 $ProblemLocation=~s/->\Q$Type_Name\E\Z//g;
17384 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017385 while($ProblemLocation=~/\-\>/g) {
17386 $Path_Length += 1;
17387 }
17388 if($MinPath_Length==-1 or ($Path_Length<=$MinPath_Length and $Severity_Val{$Severity}>$Severity_Max)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017389 or (cmpLocations($ProblemLocation, $ProblemLocation_Last) and $Severity_Val{$Severity}==$Severity_Max))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017390 {
17391 $MinPath_Length = $Path_Length;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017392 $Severity_Max = $Severity_Val{$Severity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017393 $ProblemLocation_Last = $ProblemLocation;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017394 %{$SProblems{$Symbol}} = (
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017395 "Descr"=>getAffectDesc($Level, $Symbol, $Kind, $Location),
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017396 "Severity_Max"=>$Severity_Max,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017397 "Signature"=>get_Signature($Symbol, 1),
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017398 "Position"=>$PPos,
17399 "Param_Name"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017400 "Location"=>$Location
17401 );
17402 }
17403 }
17404 }
17405 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017406 my @Symbols = keys(%SProblems);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017407 @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 +040017408 @Symbols = sort {$SProblems{$b}{"Severity_Max"}<=>$SProblems{$a}{"Severity_Max"}} @Symbols;
17409 if($#Symbols+1>$LIMIT)
17410 { # remove last element
17411 pop(@Symbols);
17412 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017413 my $Affected = "";
17414 if($ReportFormat eq "xml")
17415 { # XML
17416 $Affected .= " <affected>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017417 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017418 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017419 my $Param_Name = $SProblems{$Symbol}{"Param_Name"};
17420 my $Description = $SProblems{$Symbol}{"Descr"};
17421 my $Location = $SProblems{$Symbol}{"Location"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017422 my $Target = "";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017423 if($Param_Name)
17424 {
17425 $Target .= " param=\"$Param_Name\"";
17426 $Description=~s/parameter $Param_Name /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017427 }
17428 elsif($Location=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017429 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017430 }
17431 elsif($Location=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017432 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017433 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017434
17435 if($Description=~s/\AField ([^\s]+) /Field \@field /) {
17436 $Target .= " field=\"$1\"";
17437 }
17438
17439 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017440 $Affected .= " <comment>".xmlSpecChars($Description)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017441 $Affected .= " </symbol>\n";
17442 }
17443 $Affected .= " </affected>\n";
17444 }
17445 else
17446 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017447 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017448 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017449 my $Description = $SProblems{$Symbol}{"Descr"};
17450 my $Signature = $SProblems{$Symbol}{"Signature"};
17451 my $Pos = $SProblems{$Symbol}{"Position"};
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017452 $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 +040017453 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017454 if(keys(%SProblems)>$LIMIT) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017455 $Affected .= " ...<br/>"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017456 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017457 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017458 if($Affected)
17459 {
17460 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017461 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".(keys(%SProblems)>$LIMIT?">".$LIMIT:keys(%SProblems)).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017462 }
17463 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017464
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017465 return $Affected;
17466}
17467
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017468sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017469{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017470 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017471 if($L2=~/\A(retval|this)\b/
17472 and $L1!~/\A(retval|this)\b/)
17473 {
17474 if($L1!~/\-\>/) {
17475 return 1;
17476 }
17477 elsif($L2=~/\-\>/) {
17478 return 1;
17479 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017480 }
17481 return 0;
17482}
17483
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017484sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017485{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017486 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017487
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017488 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017489
17490 my $Location_I = $Location;
17491 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17492
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017493 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017494
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017495 if($Kind eq "Overridden_Virtual_Method"
17496 or $Kind eq "Overridden_Virtual_Method_B") {
17497 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17498 }
17499 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17500 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017501 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17502
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017503 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17504 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017505 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17506 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17507
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017508 if($ClassName eq $Problem{"Type_Name"}) {
17509 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17510 }
17511 else {
17512 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17513 }
17514 }
17515 else
17516 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017517 my $TypeID = undef;
17518
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017519 if($Location=~/retval/)
17520 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017521 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017522 push(@Sentence, "Field \'".$Location."\' in return value");
17523 }
17524 else {
17525 push(@Sentence, "Return value");
17526 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017527
17528 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017529 }
17530 elsif($Location=~/this/)
17531 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017532 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017533 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17534 }
17535 else {
17536 push(@Sentence, "\'this\' pointer");
17537 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017538
17539 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017540 }
17541 else
17542 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017543
17544 my $PName = getParamName($Location);
17545 my $PPos = getParamPos($PName, $Symbol, 1);
17546
17547 if(index($Location, "->")!=-1) {
17548 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017549 }
17550 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017551 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017552 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017553 if($PName) {
17554 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017555 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017556
17557 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17558 }
17559
17560 if($Location!~/this/)
17561 {
17562 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017563 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017564 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017565 push(@Sentence, "(pointer)");
17566 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017567 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017568 push(@Sentence, "(reference)");
17569 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017570 }
17571 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017572
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017573 if($Location eq "this") {
17574 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17575 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017576 else
17577 {
17578 my $Location_T = $Location;
17579 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17580
17581 my $TypeID_Problem = $TypeID;
17582 if($Location_T) {
17583 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17584 }
17585
17586 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17587 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17588 }
17589 else {
17590 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17591 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017592 }
17593 }
17594 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017595 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017596 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 +040017597 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017598
17599 my $Sent = join(" ", @Sentence);
17600
17601 if($ReportFormat eq "xml")
17602 {
17603 $Sent=~s/->/./g;
17604 $Sent=~s/'//g;
17605 }
17606
17607 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017608}
17609
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017610sub getFieldType($$$)
17611{
17612 my ($Location, $TypeId, $LibVersion) = @_;
17613
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017614 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017615
17616 foreach my $Name (@Fields)
17617 {
17618 my %Info = get_BaseType($TypeId, $LibVersion);
17619
17620 foreach my $Pos (keys(%{$Info{"Memb"}}))
17621 {
17622 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17623 {
17624 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17625 last;
17626 }
17627 }
17628 }
17629
17630 return $TypeId;
17631}
17632
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017633sub get_XmlSign($$)
17634{
17635 my ($Symbol, $LibVersion) = @_;
17636 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17637 my $Report = "";
17638 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17639 {
17640 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017641 my $Type = $Info->{"Param"}{$Pos}{"type"};
17642 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017643 foreach my $Typedef (keys(%ChangedTypedef))
17644 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017645 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17646 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17647 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017648 }
17649 $Report .= " <param pos=\"$Pos\">\n";
17650 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017651 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017652 $Report .= " </param>\n";
17653 }
17654 if(my $Return = $Info->{"Return"})
17655 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017656 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017657 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017658 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017659 $Report .= " </retval>\n";
17660 }
17661 return $Report;
17662}
17663
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017664sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017665{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017666 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017667 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017668 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017669 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017670 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17671 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017672 next;
17673 }
17674 $Report .= " <symbol name=\"$Symbol\">\n";
17675 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017676 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017677 {
17678 if(defined $CompleteSignature{1}{$Symbol}
17679 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17680 {
17681 $P1 = get_XmlSign($Symbol, 1);
17682 $S1 = get_Signature($Symbol, 1);
17683 }
17684 elsif($Symbol=~/\A(_Z|\?)/) {
17685 $S1 = $tr_name{$Symbol};
17686 }
17687 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017688 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017689 {
17690 if(defined $CompleteSignature{2}{$Symbol}
17691 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17692 {
17693 $P2 = get_XmlSign($Symbol, 2);
17694 $S2 = get_Signature($Symbol, 2);
17695 }
17696 elsif($Symbol=~/\A(_Z|\?)/) {
17697 $S2 = $tr_name{$Symbol};
17698 }
17699 }
17700 if($S1)
17701 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017702 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017703 $Report .= $P1;
17704 $Report .= " </old>\n";
17705 }
17706 if($S2 and $S2 ne $S1)
17707 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017708 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017709 $Report .= $P2;
17710 $Report .= " </new>\n";
17711 }
17712 $Report .= " </symbol>\n";
17713 }
17714 $Report .= "</symbols_info>\n";
17715 return $Report;
17716}
17717
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017718sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017719{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017720 my ($Level, $Report) = @_;
17721 if($ReportFormat eq "xml") {
17722 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017723 }
17724 if($StdOut)
17725 { # --stdout option
17726 print STDOUT $Report;
17727 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017728 else
17729 {
17730 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017731 mkpath(get_dirname($RPath));
17732
17733 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17734 print REPORT $Report;
17735 close(REPORT);
17736
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017737 if($Browse or $OpenReport)
17738 { # open in browser
17739 openReport($RPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017740 if($JoinReport or $DoubleReport)
17741 {
17742 if($Level eq "Binary")
17743 { # wait to open a browser
17744 sleep(1);
17745 }
17746 }
17747 }
17748 }
17749}
17750
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017751sub openReport($)
17752{
17753 my $Path = $_[0];
17754 my $Cmd = "";
17755 if($Browse)
17756 { # user-defined browser
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017757 $Cmd = $Browse." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017758 }
17759 if(not $Cmd)
17760 { # default browser
17761 if($OSgroup eq "macos") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017762 $Cmd = "open \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017763 }
17764 elsif($OSgroup eq "windows") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017765 $Cmd = "start ".path_format($Path, $OSgroup);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017766 }
17767 else
17768 { # linux, freebsd, solaris
17769 my @Browsers = (
17770 "x-www-browser",
17771 "sensible-browser",
17772 "firefox",
17773 "opera",
17774 "xdg-open",
17775 "lynx",
17776 "links"
17777 );
17778 foreach my $Br (@Browsers)
17779 {
17780 if($Br = get_CmdPath($Br))
17781 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017782 $Cmd = $Br." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017783 last;
17784 }
17785 }
17786 }
17787 }
17788 if($Cmd)
17789 {
17790 if($Debug) {
17791 printMsg("INFO", "running $Cmd");
17792 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017793 if($OSgroup ne "windows"
17794 and $OSgroup ne "macos")
17795 {
17796 if($Cmd!~/lynx|links/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017797 $Cmd .= " >\"/dev/null\" 2>&1 &";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017798 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017799 }
17800 system($Cmd);
17801 }
17802 else {
17803 printMsg("ERROR", "cannot open report in browser");
17804 }
17805}
17806
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017807sub getReport($)
17808{
17809 my $Level = $_[0];
17810 if($ReportFormat eq "xml")
17811 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017812 if($Level eq "Join")
17813 {
17814 my $Report = "<reports>\n";
17815 $Report .= getReport("Binary");
17816 $Report .= getReport("Source");
17817 $Report .= "</reports>\n";
17818 return $Report;
17819 }
17820 else
17821 {
17822 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17823 my ($Summary, $MetaData) = get_Summary($Level);
17824 $Report .= $Summary."\n";
17825 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17826 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017827
17828 # additional symbols info (if needed)
17829 # $Report .= get_Report_SymbolsInfo($Level);
17830
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017831 $Report .= "</report>\n";
17832 return $Report;
17833 }
17834 }
17835 else
17836 { # HTML
17837 my $CssStyles = readModule("Styles", "Report.css");
17838 my $JScripts = readModule("Scripts", "Sections.js");
17839 if($Level eq "Join")
17840 {
17841 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17842 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017843 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
17844 my $Keywords = $TargetLibraryFName.", compatibility, API, report";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017845 my $Description = "Compatibility report for the $TargetLibraryFName $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
17846 my ($BSummary, $BMetaData) = get_Summary("Binary");
17847 my ($SSummary, $SMetaData) = get_Summary("Source");
17848 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>";
17849 $Report .= get_Report_Header("Join")."
17850 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017851 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17852 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017853 </div>";
17854 $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>";
17855 $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 +040017856 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017857 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17858 return $Report;
17859 }
17860 else
17861 {
17862 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017863 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17864 my $Keywords = $TargetLibraryFName.", ".lc($Level)." compatibility, API, report";
17865 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 +040017866 if($Level eq "Binary")
17867 {
17868 if(getArch(1) eq getArch(2)
17869 and getArch(1) ne "unknown") {
17870 $Description .= " on ".showArch(getArch(1));
17871 }
17872 }
17873 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."\n<body>\n<div><a name='Top'></a>\n";
17874 $Report .= get_Report_Header($Level)."\n".$Summary."\n";
17875 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17876 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17877 $Report .= get_SourceInfo();
17878 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017879 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017880 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17881 return $Report;
17882 }
17883 }
17884}
17885
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017886sub getLegend()
17887{
17888 return "<br/>
17889<table class='summary'>
17890<tr>
17891 <td class='new'>added</td>
17892 <td class='passed'>compatible</td>
17893</tr>
17894<tr>
17895 <td class='warning'>warning</td>
17896 <td class='failed'>incompatible</td>
17897</tr></table>\n";
17898}
17899
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017900sub createReport()
17901{
17902 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017903 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017904 writeReport("Join", getReport("Join"));
17905 }
17906 elsif($DoubleReport)
17907 { # default
17908 writeReport("Binary", getReport("Binary"));
17909 writeReport("Source", getReport("Source"));
17910 }
17911 elsif($BinaryOnly)
17912 { # --binary
17913 writeReport("Binary", getReport("Binary"));
17914 }
17915 elsif($SourceOnly)
17916 { # --source
17917 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017918 }
17919}
17920
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017921sub getReportFooter($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017922{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017923 my ($LibName, $Wide) = @_;
17924 my $FooterStyle = $Wide?"width:99%":"width:97%;padding-top:3px";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017925 my $Footer = "<div style='$FooterStyle;font-size:11px;' align='right'><i>Generated on ".(localtime time); # report date
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017926 $Footer .= " for <span style='font-weight:bold'>$LibName</span>"; # tested library/system name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017927 $Footer .= " by <a href='".$HomePage{"Wiki"}."'>ABI Compliance Checker</a>"; # tool name
17928 my $ToolSummary = "<br/>A tool for checking backward compatibility of a C/C++ library API&#160;&#160;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017929 $Footer .= " $TOOL_VERSION &#160;$ToolSummary</i></div>"; # tool version
17930 return $Footer;
17931}
17932
17933sub get_Report_Problems($$)
17934{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017935 my ($Severity, $Level) = @_;
17936 my $Report = get_Report_TypeProblems($Severity, $Level);
17937 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017938 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017939 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017940 if($Severity eq "Low")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017941 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017942 $Report .= get_Report_ChangedConstants("Low", $Level);
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +040017943 if($ReportFormat eq "html")
17944 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017945 if($CheckImpl and $Level eq "Binary") {
17946 $Report .= get_Report_Impl();
17947 }
17948 }
17949 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017950 if($Severity eq "Safe")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017951 {
17952 $Report .= get_Report_ChangedConstants("Safe", $Level);
17953 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017954 if($ReportFormat eq "html")
17955 {
17956 if($Report)
17957 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017958 if($JoinReport)
17959 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017960 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017961 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17962 }
17963 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017964 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017965 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017966 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017967 else
17968 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017969 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017970 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17971 }
17972 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017973 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017974 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017975 }
17976 }
17977 }
17978 return $Report;
17979}
17980
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017981sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017982{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017983 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17984 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17985 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17986 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017987 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17988 <meta name=\"keywords\" content=\"$Keywords\" />
17989 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017990 <title>
17991 $Title
17992 </title>
17993 <style type=\"text/css\">
17994 $Styles
17995 </style>
17996 <script type=\"text/javascript\" language=\"JavaScript\">
17997 <!--
17998 $Scripts
17999 -->
18000 </script>
18001 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018002}
18003
18004sub insertIDs($)
18005{
18006 my $Text = $_[0];
18007 while($Text=~/CONTENT_ID/)
18008 {
18009 if(int($Content_Counter)%2) {
18010 $ContentID -= 1;
18011 }
18012 $Text=~s/CONTENT_ID/c_$ContentID/;
18013 $ContentID += 1;
18014 $Content_Counter += 1;
18015 }
18016 return $Text;
18017}
18018
18019sub checkPreprocessedUnit($)
18020{
18021 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018022 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018023 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018024 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018025
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018026 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018027 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018028 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018029 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018030 chomp($Line);
18031 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018032 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018033 $CurHeader = path_format($1, $OSgroup);
18034 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018035 $CurClass = "";
18036
18037 if(index($CurHeader, $TMP_DIR)==0) {
18038 next;
18039 }
18040
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018041 if(substr($CurHeaderName, 0, 1) eq "<")
18042 { # <built-in>, <command-line>, etc.
18043 $CurHeaderName = "";
18044 $CurHeader = "";
18045 }
18046
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018047 if($ExtraInfo)
18048 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018049 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018050 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
18051 }
18052 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018053 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018054 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018055 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018056 if($CurHeaderName)
18057 {
18058 if(not $Include_Neighbors{$Version}{$CurHeaderName}
18059 and not $Registered_Headers{$Version}{$CurHeader})
18060 { # not a target
18061 next;
18062 }
18063 if(not is_target_header($CurHeaderName, 1)
18064 and not is_target_header($CurHeaderName, 2))
18065 { # user-defined header
18066 next;
18067 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018068 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018069 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018070
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018071 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018072 {
18073 my ($Name, $Value) = ($1, $2);
18074 if(not $Constants{$Version}{$Name}{"Access"})
18075 {
18076 $Constants{$Version}{$Name}{"Access"} = "public";
18077 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018078 if($CurHeaderName) {
18079 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
18080 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018081 }
18082 }
18083 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
18084 $Constants{$Version}{$1}{"Access"} = "private";
18085 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018086 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018087 else
18088 {
18089 if(defined $ExtraDump)
18090 {
18091 if($Line=~/(\w+)\s*\(/)
18092 { # functions
18093 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18094 }
18095 #elsif($Line=~/(\w+)\s*;/)
18096 #{ # data
18097 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18098 #}
18099 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
18100 $CurClass = $2;
18101 }
18102 }
18103 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018104 }
18105 close(PREPROC);
18106 foreach my $Constant (keys(%{$Constants{$Version}}))
18107 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018108 if($Constants{$Version}{$Constant}{"Access"} eq "private")
18109 {
18110 delete($Constants{$Version}{$Constant});
18111 next;
18112 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040018113 if(not $ExtraDump and ($Constant=~/_h\Z/i
18114 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018115 { # skip
18116 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018117 }
18118 else {
18119 delete($Constants{$Version}{$Constant}{"Access"});
18120 }
18121 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018122 if($Debug)
18123 {
18124 mkpath($DEBUG_PATH{$Version});
18125 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18126 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018127}
18128
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018129sub uncoverConstant($$)
18130{
18131 my ($LibVersion, $Constant) = @_;
18132 return "" if(not $LibVersion or not $Constant);
18133 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18134 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18135 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18136 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018137
18138 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018139 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018140 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18141 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018142 {
18143 push(@RecurConstant, $Constant);
18144 my $Uncovered = uncoverConstant($LibVersion, $Value);
18145 if($Uncovered ne "") {
18146 $Value = $Uncovered;
18147 }
18148 pop(@RecurConstant);
18149 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018150
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018151 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018152 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018153 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18154 }
18155 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18156}
18157
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018158sub simpleConstant($$)
18159{
18160 my ($LibVersion, $Value) = @_;
18161 if($Value=~/\W/)
18162 {
18163 my $Value_Copy = $Value;
18164 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18165 {
18166 my $Word = $1;
18167 if($Value!~/$Word\s*\(/)
18168 {
18169 my $Val = uncoverConstant($LibVersion, $Word);
18170 if($Val ne "")
18171 {
18172 $Value=~s/\b$Word\b/$Val/g;
18173 }
18174 }
18175 }
18176 }
18177 return $Value;
18178}
18179
18180sub computeValue($)
18181{
18182 my $Value = $_[0];
18183
18184 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18185 return $1;
18186 }
18187
18188 if($Value=~/\A[\d\-\+()]+\Z/) {
18189 return eval($Value);
18190 }
18191
18192 return $Value;
18193}
18194
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018195my %IgnoreConstant = map {$_=>1} (
18196 "VERSION",
18197 "VERSIONCODE",
18198 "VERNUM",
18199 "VERS_INFO",
18200 "PATCHLEVEL",
18201 "INSTALLPREFIX",
18202 "VBUILD",
18203 "VPATCH",
18204 "VMINOR",
18205 "BUILD_STRING",
18206 "BUILD_TIME",
18207 "PACKAGE_STRING",
18208 "PRODUCTION",
18209 "CONFIGURE_COMMAND",
18210 "INSTALLDIR",
18211 "BINDIR",
18212 "CONFIG_FILE_PATH",
18213 "DATADIR",
18214 "EXTENSION_DIR",
18215 "INCLUDE_PATH",
18216 "LIBDIR",
18217 "LOCALSTATEDIR",
18218 "SBINDIR",
18219 "SYSCONFDIR",
18220 "RELEASE",
18221 "SOURCE_ID",
18222 "SUBMINOR",
18223 "MINOR",
18224 "MINNOR",
18225 "MINORVERSION",
18226 "MAJOR",
18227 "MAJORVERSION",
18228 "MICRO",
18229 "MICROVERSION",
18230 "BINARY_AGE",
18231 "INTERFACE_AGE",
18232 "CORE_ABI",
18233 "PATCH",
18234 "COPYRIGHT",
18235 "TIMESTAMP",
18236 "REVISION",
18237 "PACKAGE_TAG",
18238 "PACKAGEDATE",
18239 "NUMVERSION",
18240 "Release",
18241 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018242);
18243
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018244sub constantFilter($$$)
18245{
18246 my ($Name, $Value, $Level) = @_;
18247
18248 if($Level eq "Binary")
18249 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018250 if($Name=~/_t\Z/)
18251 { # __malloc_ptr_t
18252 return 1;
18253 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018254 foreach (keys(%IgnoreConstant))
18255 {
18256 if($Name=~/(\A|_)$_(_|\Z)/)
18257 { # version
18258 return 1;
18259 }
18260 if(/\A[A-Z].*[a-z]\Z/)
18261 {
18262 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18263 { # version
18264 return 1;
18265 }
18266 }
18267 }
18268 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18269 { # version
18270 return 1;
18271 }
18272 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18273 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18274 return 1;
18275 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018276
18277 if($Value=~/\A["'].*['"]/i)
18278 { # string
18279 return 0;
18280 }
18281
18282 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18283 { # static int gcry_pth_init
18284 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018285 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018286 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018287 return 1;
18288 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018289 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018290 { # foo(p)
18291 return 1;
18292 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018293 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018294 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018295 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018296 return 1;
18297 }
18298 }
18299
18300 return 0;
18301}
18302
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018303sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018304{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018305 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018306 foreach my $Constant (keys(%{$Constants{1}}))
18307 {
18308 if($SkipConstants{1}{$Constant})
18309 { # skipped by the user
18310 next;
18311 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018312
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018313 if(my $Header = $Constants{1}{$Constant}{"Header"})
18314 {
18315 if(not is_target_header($Header, 1)
18316 and not is_target_header($Header, 2))
18317 { # user-defined header
18318 next;
18319 }
18320 }
18321 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018322 next;
18323 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018324
18325 my $Old_Value = uncoverConstant(1, $Constant);
18326
18327 if(constantFilter($Constant, $Old_Value, $Level))
18328 { # separate binary and source problems
18329 next;
18330 }
18331
18332 if(not defined $Constants{2}{$Constant}{"Value"})
18333 { # removed
18334 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18335 "Target"=>$Constant,
18336 "Old_Value"=>$Old_Value );
18337 next;
18338 }
18339
18340 if($Constants{2}{$Constant}{"Value"} eq "")
18341 { # empty value
18342 # TODO: implement a rule
18343 next;
18344 }
18345
18346 my $New_Value = uncoverConstant(2, $Constant);
18347
18348 my $Old_Value_Pure = $Old_Value;
18349 my $New_Value_Pure = $New_Value;
18350
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018351 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18352 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18353 $New_Value_Pure=~s/(\W)\s+/$1/g;
18354 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018355
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018356 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018357
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018358 if($New_Value_Pure ne $Old_Value_Pure)
18359 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018360 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18361 { # complex values
18362 next;
18363 }
18364 if(computeValue($Old_Value) eq computeValue($New_Value))
18365 { # expressions
18366 next;
18367 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018368 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18369 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18370 next;
18371 }
18372 if($Old_Value eq "0" and $New_Value eq "NULL")
18373 { # 0 => NULL
18374 next;
18375 }
18376 if($Old_Value eq "NULL" and $New_Value eq "0")
18377 { # NULL => 0
18378 next;
18379 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018380 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018381 "Target"=>$Constant,
18382 "Old_Value"=>$Old_Value,
18383 "New_Value"=>$New_Value );
18384 }
18385 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018386
18387 foreach my $Constant (keys(%{$Constants{2}}))
18388 {
18389 if(not defined $Constants{1}{$Constant}{"Value"})
18390 {
18391 if($SkipConstants{2}{$Constant})
18392 { # skipped by the user
18393 next;
18394 }
18395
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018396 if(my $Header = $Constants{2}{$Constant}{"Header"})
18397 {
18398 if(not is_target_header($Header, 1)
18399 and not is_target_header($Header, 2))
18400 { # user-defined header
18401 next;
18402 }
18403 }
18404 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018405 next;
18406 }
18407
18408 my $New_Value = uncoverConstant(2, $Constant);
18409 if(not defined $New_Value or $New_Value eq "") {
18410 next;
18411 }
18412
18413 if(constantFilter($Constant, $New_Value, $Level))
18414 { # separate binary and source problems
18415 next;
18416 }
18417
18418 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18419 "Target"=>$Constant,
18420 "New_Value"=>$New_Value );
18421 }
18422 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018423}
18424
18425sub convert_integer($)
18426{
18427 my $Value = $_[0];
18428 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018429 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018430 return hex($Value);
18431 }
18432 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018433 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018434 return oct($Value);
18435 }
18436 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018437 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018438 return oct($Value);
18439 }
18440 else {
18441 return $Value;
18442 }
18443}
18444
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018445sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018446{
18447 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018448 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018449 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018450 {
18451 if($LibVersion==1)
18452 {
18453 printMsg("WARNING", "checking headers only");
18454 $CheckHeadersOnly = 1;
18455 }
18456 else {
18457 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18458 }
18459 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018460
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018461 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018462 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018463 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018464
18465 if($CheckUndefined)
18466 {
18467 my %UndefinedLibs = ();
18468
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018469 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18470
18471 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018472 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018473 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018474 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018475 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018476 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018477 if($Symbol_Library{$LibVersion}{$Symbol}
18478 or $DepSymbol_Library{$LibVersion}{$Symbol})
18479 { # exported by target library
18480 next;
18481 }
18482 if(index($Symbol, '@')!=-1)
18483 { # exported default symbol version (@@)
18484 $Symbol=~s/\@/\@\@/;
18485 if($Symbol_Library{$LibVersion}{$Symbol}
18486 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18487 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018488 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018489 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018490 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18491 $UndefinedLibs{$Path} = 1;
18492 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018493 }
18494 }
18495 }
18496 if($ExtraInfo)
18497 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018498 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018499 {
18500 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018501 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018502 foreach (@Paths)
18503 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018504 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018505 my ($Dir, $Name) = separate_path($_);
18506
18507 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018508 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018509 }
18510
18511 $Name = parse_libname($Name, "name", $OStarget);
18512 $Name=~s/\Alib//;
18513
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018514 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018515 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018516
18517 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18518 {
18519 $LibString = " -L".esc($Dir).$LibString;
18520 }
18521
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018522 writeFile($ExtraInfo."/libs-string", $LibString);
18523 }
18524 }
18525 }
18526
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018527 if($ExtraInfo) {
18528 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18529 }
18530
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018531 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018532 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018533 if($#LibPaths!=-1)
18534 {
18535 if(not keys(%{$Symbol_Library{$LibVersion}}))
18536 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018537 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018538 printMsg("WARNING", "checking headers only");
18539 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018540 }
18541 }
18542 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018543
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018544 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018545 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018546}
18547
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018548my %Prefix_Lib_Map=(
18549 # symbols for autodetecting library dependencies (by prefix)
18550 "pthread_" => ["libpthread"],
18551 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18552 "cairo_" => ["libcairo"],
18553 "gtk_" => ["libgtk-x11-2.0"],
18554 "atk_" => ["libatk-1.0"],
18555 "gdk_" => ["libgdk-x11-2.0"],
18556 "gl" => ["libGL"],
18557 "glu" => ["libGLU"],
18558 "popt" => ["libpopt"],
18559 "Py" => ["libpython"],
18560 "jpeg_" => ["libjpeg"],
18561 "BZ2_" => ["libbz2"],
18562 "Fc" => ["libfontconfig"],
18563 "Xft" => ["libXft"],
18564 "SSL_" => ["libssl"],
18565 "sem_" => ["libpthread"],
18566 "snd_" => ["libasound"],
18567 "art_" => ["libart_lgpl_2"],
18568 "dbus_g" => ["libdbus-glib-1"],
18569 "GOMP_" => ["libgomp"],
18570 "omp_" => ["libgomp"],
18571 "cms" => ["liblcms"]
18572);
18573
18574my %Pattern_Lib_Map=(
18575 "SL[a-z]" => ["libslang"]
18576);
18577
18578my %Symbol_Lib_Map=(
18579 # symbols for autodetecting library dependencies (by name)
18580 "pow" => "libm",
18581 "fmod" => "libm",
18582 "sin" => "libm",
18583 "floor" => "libm",
18584 "cos" => "libm",
18585 "dlopen" => "libdl",
18586 "deflate" => "libz",
18587 "inflate" => "libz",
18588 "move_panel" => "libpanel",
18589 "XOpenDisplay" => "libX11",
18590 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018591 "clock_gettime" => "librt",
18592 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018593);
18594
18595sub find_SymbolLibs($$)
18596{
18597 my ($LibVersion, $Symbol) = @_;
18598
18599 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18600 { # debug symbols
18601 return ();
18602 }
18603
18604 my %Paths = ();
18605
18606 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18607 {
18608 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18609 $Paths{$Path} = 1;
18610 }
18611 }
18612
18613 if(my $SymbolPrefix = getPrefix($Symbol))
18614 {
18615 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18616 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18617 }
18618
18619 if(not keys(%Paths))
18620 {
18621 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18622 {
18623 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18624 {
18625 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18626 $Paths{$Path} = 1;
18627 }
18628 }
18629 }
18630 }
18631
18632 if(not keys(%Paths))
18633 {
18634 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18635 {
18636 if($Symbol=~/\A$Prefix/)
18637 {
18638 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18639 {
18640 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18641 $Paths{$Path} = 1;
18642 }
18643 }
18644 }
18645 }
18646 }
18647
18648 if(not keys(%Paths))
18649 {
18650 if($SymbolPrefix)
18651 { # try to find a library by symbol prefix
18652 if($SymbolPrefix eq "inotify" and
18653 index($Symbol, "\@GLIBC")!=-1)
18654 {
18655 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18656 $Paths{$Path} = 1;
18657 }
18658 }
18659 else
18660 {
18661 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18662 $Paths{$Path} = 1;
18663 }
18664 }
18665 }
18666 }
18667
18668 if(my @Paths = keys(%Paths)) {
18669 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18670 }
18671 }
18672 return keys(%Paths);
18673}
18674
18675sub get_LibPath_Prefix($$)
18676{
18677 my ($LibVersion, $Prefix) = @_;
18678
18679 $Prefix = lc($Prefix);
18680 $Prefix=~s/[_]+\Z//g;
18681
18682 foreach ("-2", "2", "-1", "1", "")
18683 { # libgnome-2.so
18684 # libxml2.so
18685 # libdbus-1.so
18686 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18687 return $Path;
18688 }
18689 }
18690 return "";
18691}
18692
18693sub getPrefix($)
18694{
18695 my $Str = $_[0];
18696 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18697 { # XmuValidArea: Xmu
18698 return $1;
18699 }
18700 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18701 { # snfReadFont: snf
18702 return $1;
18703 }
18704 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18705 { # XRRTimes: XRR
18706 return $1;
18707 }
18708 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18709 { # H5HF_delete: H5
18710 return $1;
18711 }
18712 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18713 { # alarm_event_add: alarm_
18714 return $1;
18715 }
18716 elsif($Str=~/\A(([a-z])\2{1,})/i)
18717 { # ffopen
18718 return $1;
18719 }
18720 return "";
18721}
18722
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018723sub getSymbolSize($$)
18724{ # size from the shared library
18725 my ($Symbol, $LibVersion) = @_;
18726 return 0 if(not $Symbol);
18727 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18728 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18729 {
18730 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18731 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18732 {
18733 if($Size<0) {
18734 return -$Size;
18735 }
18736 }
18737 }
18738 return 0;
18739}
18740
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018741sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018742{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18743 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018744 my ($Name, $Type) = @_;
18745
18746 # single
18747 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018748 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018749 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018750 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018751 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018752
18753 # double
18754 if($Name=~/$DEFAULT_STD_PARMS/)
18755 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018756 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018757 {
18758 my ($ShortName, $FuncParams) = split_Signature($Name);
18759
18760 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18761 {
18762 if(index($FParam, "<")!=-1)
18763 {
18764 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18765 my $FParam_N = canonifyName($FParam, "T");
18766 if($FParam_N ne $FParam) {
18767 $Name=~s/\Q$FParam\E/$FParam_N/g;
18768 }
18769 }
18770 }
18771 }
18772 elsif($Type eq "T")
18773 {
18774 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18775
18776 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018777 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018778 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018779 my $FParam = $TParams[0];
18780 foreach my $Pos (1 .. $#TParams)
18781 {
18782 my $TParam = $TParams[$Pos];
18783 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18784 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18785 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018786 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018787 }
18788 }
18789 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018790 if($Type eq "S") {
18791 return formatName($Name, "S");
18792 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018793 return $Name;
18794}
18795
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018796sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018797{
18798 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018799 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018800 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018801 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018802 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018803 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018804 next if($tr_name{$Symbol});
18805 $Symbol=~s/[\@\$]+(.*)\Z//;
18806 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018807 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018808 elsif(index($Symbol, "?")==0)
18809 {
18810 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018811 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018812 }
18813 else
18814 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018815 $tr_name{$Symbol} = $Symbol;
18816 $mangled_name_gcc{$Symbol} = $Symbol;
18817 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018818 }
18819 }
18820 if($#MnglNames1 > -1)
18821 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018822 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018823 foreach my $MnglName (@MnglNames1)
18824 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018825 if(my $Unmangled = pop(@UnmangledNames))
18826 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018827 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018828 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18829 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18830 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018831 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018832 and $tr_name{$MnglName}=~/vtable for (.+)/)
18833 { # bind class name and v-table symbol
18834 my $ClassName = $1;
18835 $ClassVTable{$ClassName} = $MnglName;
18836 $VTableClass{$MnglName} = $ClassName;
18837 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018838 }
18839 }
18840 }
18841 if($#MnglNames2 > -1)
18842 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018843 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018844 foreach my $MnglName (@MnglNames2)
18845 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018846 if(my $Unmangled = pop(@UnmangledNames))
18847 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018848 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018849 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18850 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018851 }
18852 }
18853 return \%tr_name;
18854}
18855
18856sub link_symbol($$$)
18857{
18858 my ($Symbol, $RunWith, $Deps) = @_;
18859 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18860 return 1;
18861 }
18862 if($Deps eq "+Deps")
18863 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018864 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018865 return 1;
18866 }
18867 }
18868 return 0;
18869}
18870
18871sub link_symbol_internal($$$)
18872{
18873 my ($Symbol, $RunWith, $Where) = @_;
18874 return 0 if(not $Where or not $Symbol);
18875 if($Where->{$RunWith}{$Symbol})
18876 { # the exact match by symbol name
18877 return 1;
18878 }
18879 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18880 { # indirect symbol version, i.e.
18881 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018882 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018883 if($Where->{$RunWith}{$VSym}) {
18884 return 1;
18885 }
18886 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018887 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018888 if($Sym and $Ver)
18889 { # search for the symbol with the same version
18890 # or without version
18891 if($Where->{$RunWith}{$Sym})
18892 { # old: foo@v|foo@@v
18893 # new: foo
18894 return 1;
18895 }
18896 if($Where->{$RunWith}{$Sym."\@".$Ver})
18897 { # old: foo|foo@@v
18898 # new: foo@v
18899 return 1;
18900 }
18901 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18902 { # old: foo|foo@v
18903 # new: foo@@v
18904 return 1;
18905 }
18906 }
18907 return 0;
18908}
18909
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018910sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018911{
18912 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018913 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018914 my @Imported = ();
18915 if($OSgroup eq "macos")
18916 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018917 my $NM = get_CmdPath("nm");
18918 if(not $NM) {
18919 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018920 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018921 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018922 while(<APP>)
18923 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018924 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018925 push(@Imported, $1);
18926 }
18927 }
18928 close(APP);
18929 }
18930 elsif($OSgroup eq "windows")
18931 {
18932 my $DumpBinCmd = get_CmdPath("dumpbin");
18933 if(not $DumpBinCmd) {
18934 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18935 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018936 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018937 while(<APP>)
18938 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018939 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18940 push(@Imported, $1);
18941 }
18942 }
18943 close(APP);
18944 }
18945 else
18946 {
18947 my $ReadelfCmd = get_CmdPath("readelf");
18948 if(not $ReadelfCmd) {
18949 exitStatus("Not_Found", "can't find \"readelf\"");
18950 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018951 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018952 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018953 while(<APP>)
18954 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018955 if(defined $symtab)
18956 { # do nothing with symtab
18957 if(index($_, "'.dynsym'")!=-1)
18958 { # dynamic table
18959 $symtab = undef;
18960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018961 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018962 elsif(index($_, "'.symtab'")!=-1)
18963 { # symbol table
18964 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018965 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018966 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018967 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018968 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18969 if($Ndx eq "UND")
18970 { # only imported symbols
18971 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018972 }
18973 }
18974 }
18975 close(APP);
18976 }
18977 return @Imported;
18978}
18979
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018980my %ELF_BIND = map {$_=>1} (
18981 "WEAK",
18982 "GLOBAL"
18983);
18984
18985my %ELF_TYPE = map {$_=>1} (
18986 "FUNC",
18987 "IFUNC",
18988 "OBJECT",
18989 "COMMON"
18990);
18991
18992my %ELF_VIS = map {$_=>1} (
18993 "DEFAULT",
18994 "PROTECTED"
18995);
18996
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018997sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018998{ # read the line of 'readelf' output corresponding to the symbol
18999 my @Info = split(/\s+/, $_[0]);
19000 # Num: Value Size Type Bind Vis Ndx Name
19001 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019002 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019003 shift(@Info); # spaces
19004 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019005
19006 if($#Info==7)
19007 { # UND SYMBOL (N)
19008 if($Info[7]=~/\(\d+\)/) {
19009 pop(@Info);
19010 }
19011 }
19012
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019013 if($#Info!=6)
19014 { # other lines
19015 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019016 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019017 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019018 return () if(not defined $ELF_BIND{$Info[3]});
19019 return () if(not defined $ELF_VIS{$Info[4]});
19020 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
19021 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
19022 return ();
19023 }
19024 if($OStarget eq "symbian")
19025 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
19026 if(index($Info[6], "_._.absent_export_")!=-1)
19027 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
19028 return ();
19029 }
19030 $Info[6]=~s/\@.+//g; # remove version
19031 }
19032 if(index($Info[2], "0x") == 0)
19033 { # size == 0x3d158
19034 $Info[2] = hex($Info[2]);
19035 }
19036 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019037}
19038
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019039sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019040{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019041 my ($LibVersion, $Name) = @_;
19042 return "" if(not $LibVersion or not $Name);
19043 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
19044 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019045 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019046 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
19047}
19048
19049sub get_LibPath_I($$)
19050{
19051 my ($LibVersion, $Name) = @_;
19052 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019053 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019054 if(-f $Name)
19055 { # absolute path
19056 return $Name;
19057 }
19058 else
19059 { # broken
19060 return "";
19061 }
19062 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019063 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019064 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019065 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019066 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019067 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019068 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019069 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019070 }
19071 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
19072 { # ldconfig default paths
19073 return $DefaultPath;
19074 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019075 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019076 { # search in default linker directories
19077 # and then in all system paths
19078 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019079 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019080 }
19081 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019082 if(not defined $Cache{"checkSystemFiles"}) {
19083 checkSystemFiles();
19084 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019085 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
19086 return $AllObjects[0];
19087 }
19088 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
19089 {
19090 if($ShortName ne $Name)
19091 { # FIXME: check this case
19092 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
19093 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019094 }
19095 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019096 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019097 # can't find
19098 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019099}
19100
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019101sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019102{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019103 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
19104 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019105
19106 my $Real_Path = realpath($Lib_Path);
19107
19108 if(not $Real_Path)
19109 { # broken link
19110 return ();
19111 }
19112
19113 my $Lib_Name = get_filename($Real_Path);
19114
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019115 if($ExtraInfo)
19116 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019117 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019118 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019119 }
19120
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019121 if($IsNeededLib)
19122 {
19123 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19124 return ();
19125 }
19126 }
19127 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019128 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019129
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019130 if($CheckImpl)
19131 {
19132 if(not $IsNeededLib) {
19133 getImplementations($LibVersion, $Lib_Path);
19134 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019135 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019136
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019137 push(@RecurLib, $Lib_Name);
19138 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019139 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19140
19141 if(not $IsNeededLib)
19142 { # special cases: libstdc++ and libc
19143 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19144 {
19145 if($ShortName eq "libstdc++")
19146 { # libstdc++.so.6
19147 $STDCXX_TESTING = 1;
19148 }
19149 elsif($ShortName eq "libc")
19150 { # libc-2.11.3.so
19151 $GLIBC_TESTING = 1;
19152 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019153 }
19154 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019155 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019156 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019157 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019158 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019159 mkpath(get_dirname($DebugPath));
19160 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019161 if($OStarget eq "macos")
19162 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019163 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019164 if(not $NM) {
19165 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019166 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019167 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019168 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019169 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019170 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019171 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019172 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019173 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019174 else
19175 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019176 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019177 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019178 while(<LIB>)
19179 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019180 if($CheckUndefined)
19181 {
19182 if(not $IsNeededLib)
19183 {
19184 if(/ U _([\w\$]+)\s*\Z/)
19185 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019186 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019187 next;
19188 }
19189 }
19190 }
19191
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019192 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019193 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019194 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019195 if($IsNeededLib)
19196 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019197 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019198 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019199 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19200 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019202 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019203 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019204 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019205 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19206 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019207 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19208 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019209 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019210 setLanguage($LibVersion, "C++");
19211 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019212 }
19213 if($CheckObjectsOnly
19214 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019215 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019216 }
19217 }
19218 }
19219 }
19220 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019221
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019222 if($Deps)
19223 {
19224 if($LIB_TYPE eq "dynamic")
19225 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019226
19227 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019228 if(not $OtoolCmd) {
19229 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019230 }
19231
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019232 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19233 while(<LIB>)
19234 {
19235 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19236 and $1 ne $Lib_Path) {
19237 $NeededLib{$1} = 1;
19238 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019239 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019240 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019241 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019242 }
19243 }
19244 elsif($OStarget eq "windows")
19245 { # Windows *.dll, *.lib
19246 my $DumpBinCmd = get_CmdPath("dumpbin");
19247 if(not $DumpBinCmd) {
19248 exitStatus("Not_Found", "can't find \"dumpbin\"");
19249 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019250 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019251 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019252 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019253 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019254 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019255 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019256 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019257 else
19258 { # write to pipe
19259 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019260 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019261 while(<LIB>)
19262 { # 1197 4AC 0000A620 SetThreadStackGuarantee
19263 # 1198 4AD SetThreadToken (forwarded to ...)
19264 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019265 # 1 0 00005B30 ??0?N = ... (with pdb)
19266 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019267 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019268 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019269 { # dynamic, static and forwarded symbols
19270 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019271 if($IsNeededLib)
19272 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019273 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019274 {
19275 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19276 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19277 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019278 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019279 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019280 {
19281 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19282 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019283 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19284 {
19285 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19286 setLanguage($LibVersion, "C++");
19287 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019288 }
19289 if($CheckObjectsOnly
19290 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019291 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019292 }
19293 }
19294 }
19295 }
19296 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019297
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019298 if($Deps)
19299 {
19300 if($LIB_TYPE eq "dynamic")
19301 { # dependencies
19302 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19303 while(<LIB>)
19304 {
19305 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19306 and $1 ne $Lib_Path) {
19307 $NeededLib{path_format($1, $OSgroup)} = 1;
19308 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019309 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019310 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019311 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019312 }
19313 }
19314 else
19315 { # Unix; *.so, *.a
19316 # Symbian: *.dso, *.lib
19317 my $ReadelfCmd = get_CmdPath("readelf");
19318 if(not $ReadelfCmd) {
19319 exitStatus("Not_Found", "can't find \"readelf\"");
19320 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019321 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019322 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019323 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019324 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019325 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019326 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019327 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019328 else
19329 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019330 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019331 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019332 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019333 while(<LIB>)
19334 {
19335 if($LIB_TYPE eq "dynamic")
19336 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019337 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019338 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019339 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019340 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019341 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019342 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019343 # do nothing with symtab
19344 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019345 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019346 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019347 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019348 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019349 next;
19350 }
19351 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019352 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019353 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019354 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019355 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019356 if($CheckUndefined)
19357 {
19358 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019359 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019360 }
19361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019362 next;
19363 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019364 if($Bind eq "WEAK")
19365 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019366 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019367 if($Weak eq "-Weak")
19368 { # skip WEAK symbols
19369 next;
19370 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019371 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019372 my $Short = $Symbol;
19373 $Short=~s/\@.+//g;
19374 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019375 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019376 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19377 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019378 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019379 if($IsNeededLib)
19380 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019381 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019382 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019383 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19384 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019385 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019386 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019387 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019388 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019389 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19390 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19391 if($Vers)
19392 {
19393 if($LIB_EXT eq "so")
19394 { # value
19395 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19396 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19397 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019398 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019399 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19400 {
19401 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19402 setLanguage($LibVersion, "C++");
19403 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019404 }
19405 if($CheckObjectsOnly
19406 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019407 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019408 }
19409 }
19410 }
19411 }
19412 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019413
19414 if($Deps and $LIB_TYPE eq "dynamic")
19415 { # dynamic library specifics
19416 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19417 open(LIB, $Cmd." |");
19418
19419 while(<LIB>)
19420 {
19421 if(/NEEDED.+\[([^\[\]]+)\]/)
19422 { # dependencies:
19423 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19424 $NeededLib{$1} = 1;
19425 }
19426 }
19427
19428 close(LIB);
19429 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019430 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019431 if($Vers)
19432 {
19433 if(not $IsNeededLib and $LIB_EXT eq "so")
19434 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019435 my %Found = ();
19436
19437 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019438 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019439 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019440 next if(index($Symbol,"\@")==-1);
19441 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019442 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019443 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019444 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019445 if($Symbol_SameValue ne $Symbol
19446 and index($Symbol_SameValue,"\@")==-1)
19447 {
19448 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019449 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019450 last;
19451 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019452 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019453 }
19454 }
19455
19456 # default
19457 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19458 {
19459 next if(defined $Found{$Symbol});
19460 next if(index($Symbol,"\@\@")==-1);
19461
19462 if($Symbol=~/\A([^\@]*)\@\@/
19463 and not $SymVer{$LibVersion}{$1})
19464 {
19465 $SymVer{$LibVersion}{$1} = $Symbol;
19466 $Found{$Symbol} = 1;
19467 }
19468 }
19469
19470 # non-default
19471 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19472 {
19473 next if(defined $Found{$Symbol});
19474 next if(index($Symbol,"\@")==-1);
19475
19476 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19477 and not $SymVer{$LibVersion}{$1})
19478 {
19479 $SymVer{$LibVersion}{$1} = $Symbol;
19480 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019481 }
19482 }
19483 }
19484 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019485 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019486 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019487 foreach my $DyLib (sort keys(%NeededLib))
19488 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019489 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19490
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019491 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19492 {
19493 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19494 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19495 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019496 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019497 }
19498 }
19499 pop(@RecurLib);
19500 return $Library_Symbol{$LibVersion};
19501}
19502
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019503sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019504{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019505 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019506 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019507 return keys(%Prefixes);
19508}
19509
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019510sub get_prefixes_I($$)
19511{
19512 foreach my $P (@{$_[0]})
19513 {
19514 my @Parts = reverse(split(/[\/\\]+/, $P));
19515 my $Name = $Parts[0];
19516 foreach (1 .. $#Parts)
19517 {
19518 $_[1]->{$Name}{$P} = 1;
19519 last if($_>4 or $Parts[$_] eq "include");
19520 $Name = $Parts[$_].$SLASH.$Name;
19521 }
19522 }
19523}
19524
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019525sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019526{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019527 $Cache{"checkSystemFiles"} = 1;
19528
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019529 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019530
19531 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019532 {
19533 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019534
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019535 my @Files = cmd_find($DevelPath,"f");
19536 foreach my $Link (cmd_find($DevelPath,"l"))
19537 { # add symbolic links
19538 if(-f $Link) {
19539 push(@Files, $Link);
19540 }
19541 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019542
19543 if(not $CheckObjectsOnly)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019544 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019545 # search for headers in /usr/lib
Andrey Ponomarenko13bb0332013-06-28 15:32:28 +040019546 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19547 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19548 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019549 }
19550
19551 # search for libraries in /usr/lib (including symbolic links)
19552 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19553 foreach my $Path (@Libs)
19554 {
19555 my $N = get_filename($Path);
19556 $SystemObjects{$N}{$Path} = 1;
19557 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019558 }
19559 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019560
19561 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019562 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019563 foreach my $DevelPath (@{$SystemPaths{"include"}})
19564 {
19565 next if(not -d $DevelPath);
19566 # search for all header files in the /usr/include
19567 # with or without extension (ncurses.h, QtCore, ...)
19568 push(@SysHeaders, cmd_find($DevelPath,"f"));
19569 foreach my $Link (cmd_find($DevelPath,"l"))
19570 { # add symbolic links
19571 if(-f $Link) {
19572 push(@SysHeaders, $Link);
19573 }
19574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019575 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019576 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019577 }
19578}
19579
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019580sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019581{
19582 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019583 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019584 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19585 {
19586 if(not -e $Dest) {
19587 exitStatus("Access_Error", "can't access \'$Dest\'");
19588 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019589 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019590 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19591 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019592 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019593 }
19594 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019595 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019596}
19597
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019598sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019599{
19600 my ($Path, $LibVersion) = @_;
19601 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019602 my $Name = get_filename($Path);
19603 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019604 return 1;
19605 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019606 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019607 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19608 return 1;
19609 }
19610 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19611 {
19612 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19613 return 1;
19614 }
19615 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019616 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019617 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019618 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019619 return 1;
19620 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019621 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019622 return 1;
19623 }
19624 }
19625 return 0;
19626}
19627
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019628sub specificHeader($$)
19629{
19630 my ($Header, $Spec) = @_;
19631 my $Name = get_filename($Header);
19632
19633 if($Spec eq "windows")
19634 {# MS Windows
19635 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19636 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19637 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19638 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19639 my @Dirs = (
19640 "win32",
19641 "win64",
19642 "win",
19643 "windows",
19644 "msvcrt"
19645 ); # /gsf-win32/
19646 if(my $DIRs = join("|", @Dirs)) {
19647 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19648 }
19649 }
19650 elsif($Spec eq "macos")
19651 { # Mac OS
19652 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19653 }
19654
19655 return 0;
19656}
19657
19658sub skipAlienHeader($)
19659{
19660 my $Path = $_[0];
19661 my $Name = get_filename($Path);
19662 my $Dir = get_dirname($Path);
19663
19664 if($Tolerance=~/2/)
19665 { # 2 - skip internal headers
19666 my @Terms = (
19667 "p",
19668 "priv",
19669 "int",
19670 "impl",
19671 "implementation",
19672 "internal",
19673 "private",
19674 "old",
19675 "compat",
19676 "debug",
19677 "test",
19678 "gen"
19679 );
19680
19681 my @Dirs = (
19682 "private",
19683 "priv",
19684 "port",
19685 "impl",
19686 "internal",
19687 "detail",
19688 "details",
19689 "old",
19690 "compat",
19691 "debug",
19692 "config",
19693 "compiler",
19694 "platform",
19695 "test"
19696 );
19697
19698 if(my $TERMs = join("|", @Terms)) {
19699 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19700 }
19701 if(my $DIRs = join("|", @Dirs)) {
19702 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19703 }
19704
19705 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19706 }
19707
19708 if($Tolerance=~/1/)
19709 { # 1 - skip non-Linux headers
19710 if($OSgroup ne "windows")
19711 {
19712 if(specificHeader($Path, "windows")) {
19713 return 1;
19714 }
19715 }
19716 if($OSgroup ne "macos")
19717 {
19718 if(specificHeader($Path, "macos")) {
19719 return 1;
19720 }
19721 }
19722 }
19723
19724 # valid
19725 return 0;
19726}
19727
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019728sub skipHeader($$)
19729{
19730 my ($Path, $LibVersion) = @_;
19731 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019732 if(defined $Cache{"skipHeader"}{$Path}) {
19733 return $Cache{"skipHeader"}{$Path};
19734 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019735 if(defined $Tolerance and $Tolerance=~/1|2/)
19736 { # --tolerant
19737 if(skipAlienHeader($Path)) {
19738 return ($Cache{"skipHeader"}{$Path} = 1);
19739 }
19740 }
19741 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19742 return 0;
19743 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019744 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19745}
19746
19747sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019748{ # returns:
19749 # 1 - if header should NOT be included and checked
19750 # 2 - if header should NOT be included, but should be checked
19751 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019752 my $Name = get_filename($Path);
19753 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019754 return $Kind;
19755 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019756 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19757 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019758 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019759 if(index($Path, $D)!=-1)
19760 {
19761 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19762 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19763 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019764 }
19765 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019766 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19767 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019768 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019769 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19770 {
19771 if($Name=~/$P/) {
19772 return $Kind;
19773 }
19774 if($P=~/[\/\\]/ and $Path=~/$P/) {
19775 return $Kind;
19776 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019777 }
19778 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019779
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019780 return 0;
19781}
19782
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019783sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019784{
19785 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019786 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019787 { # system directory
19788 return;
19789 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019790 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019791 { # already registered
19792 return;
19793 }
19794 foreach my $Path (find_libs($Dir,"",1))
19795 {
19796 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019797 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019798 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019799 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019800 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19801}
19802
19803sub registerObject($$)
19804{
19805 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019806
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019807 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019808 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019809 if($OSgroup=~/linux|bsd/i)
19810 {
19811 if(my $SONAME = getSONAME($Path)) {
19812 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19813 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019814 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019815 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19816 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019817 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019818
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019819 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019820 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019821 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019822 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019823 if($ObjArch ne getArch_GCC($LibVersion))
19824 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19825 $CheckedArch{$LibVersion} = 1;
19826 printMsg("WARNING", "the architectures of input objects and the used GCC compiler are not equal, please change the compiler by --gcc-path=PATH option.");
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019827 }
19828 }
19829 }
19830}
19831
19832sub getArch_Object($)
19833{
19834 my $Path = $_[0];
19835
19836 my %MachineType = (
19837 "14C" => "x86",
19838 "8664" => "x86_64",
19839 "1C0" => "arm",
19840 "200" => "ia64"
19841 );
19842
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019843 my %ArchName = (
19844 "s390:31-bit" => "s390",
19845 "s390:64-bit" => "s390x",
19846 "powerpc:common" => "ppc32",
19847 "powerpc:common64" => "ppc64",
19848 "i386:x86-64" => "x86_64",
19849 "mips:3000" => "mips",
19850 "sparc:v8plus" => "sparcv9"
19851 );
19852
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019853 if($OSgroup eq "windows")
19854 {
19855 my $DumpbinCmd = get_CmdPath("dumpbin");
19856 if(not $DumpbinCmd) {
19857 exitStatus("Not_Found", "can't find \"dumpbin\"");
19858 }
19859
19860 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19861 my $Out = `$Cmd`;
19862
19863 if($Out=~/(\w+)\smachine/)
19864 {
19865 if(my $Type = $MachineType{uc($1)})
19866 {
19867 return $Type;
19868 }
19869 }
19870 }
19871 elsif($OSgroup=~/linux|bsd/)
19872 {
19873 my $ObjdumpCmd = get_CmdPath("objdump");
19874 if(not $ObjdumpCmd) {
19875 exitStatus("Not_Found", "can't find \"objdump\"");
19876 }
19877
19878 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
19879 my $Out = `$Cmd`;
19880
19881 if($Out=~/architecture:\s+([\w\-\:]+)/)
19882 {
19883 my $Arch = $1;
19884 if($Arch=~s/\:(.+)//)
19885 {
19886 my $Suffix = $1;
19887
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019888 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019889 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019890 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019891 }
19892 }
19893
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019894 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019895 $Arch = "x86";
19896 }
19897
19898 if($Arch eq "x86-64") {
19899 $Arch = "x86_64";
19900 }
19901
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019902 if($Arch eq "ia64-elf64") {
19903 $Arch = "ia64";
19904 }
19905
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019906 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019907 }
19908 }
19909 else
19910 { # macos, etc.
19911 # TODO
19912 }
19913
19914 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019915}
19916
19917sub getSONAME($)
19918{
19919 my $Path = $_[0];
19920 return if(not $Path);
19921 if(defined $Cache{"getSONAME"}{$Path}) {
19922 return $Cache{"getSONAME"}{$Path};
19923 }
19924 my $ObjdumpCmd = get_CmdPath("objdump");
19925 if(not $ObjdumpCmd) {
19926 exitStatus("Not_Found", "can't find \"objdump\"");
19927 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019928 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019929 if($OSgroup eq "windows") {
19930 $SonameCmd .= " | find \"SONAME\"";
19931 }
19932 else {
19933 $SonameCmd .= " | grep SONAME";
19934 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019935 if(my $SonameInfo = `$SonameCmd`)
19936 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019937 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19938 return ($Cache{"getSONAME"}{$Path} = $1);
19939 }
19940 }
19941 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019942}
19943
19944sub getSOPaths_Dest($$)
19945{
19946 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019947 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019948 return ();
19949 }
19950 if(-f $Dest)
19951 {
19952 if(not parse_libname($Dest, "name", $OStarget)) {
19953 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19954 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019955 registerObject($Dest, $LibVersion);
19956 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019957 return ($Dest);
19958 }
19959 elsif(-d $Dest)
19960 {
19961 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019962 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019963 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019964 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19965 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019966 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019967 { # all files and symlinks that match the name of a library
19968 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19969 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019970 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019971 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019972 }
19973 }
19974 }
19975 else
19976 { # search for all files and symlinks
19977 foreach my $Path (find_libs($Dest,"",""))
19978 {
19979 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019980 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019981 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019982 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019983 }
19984 if($OSgroup eq "macos")
19985 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019986 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019987 {
19988 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019989 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019990 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019991 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19992 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019993 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019994 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019995 }
19996 }
19997 }
19998 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019999 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020000 }
20001 else {
20002 return ();
20003 }
20004}
20005
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020006sub isCyclical($$)
20007{
20008 my ($Stack, $Value) = @_;
20009 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020010}
20011
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020012sub getGCC_Opts($)
20013{ # to use in module
20014 my $LibVersion = $_[0];
20015
20016 my @Opts = ();
20017
20018 if($CompilerOptions{$LibVersion})
20019 { # user-defined options
20020 push(@Opts, $CompilerOptions{$LibVersion});
20021 }
20022 if($GccOptions)
20023 { # additional
20024 push(@Opts, $GccOptions);
20025 }
20026
20027 if(@Opts) {
20028 return join(" ", @Opts);
20029 }
20030
20031 return undef;
20032}
20033
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020034sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020035{
20036 my $LibVersion = $_[0];
20037
20038 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
20039 return $Cache{"getArch_GCC"}{$LibVersion};
20040 }
20041
20042 my $Arch = undef;
20043
20044 if($GCC_PATH)
20045 {
20046 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
20047
20048 my $Cmd = $GCC_PATH." test.c -o test";
20049 if(my $Opts = getGCC_Opts($LibVersion))
20050 { # user-defined options
20051 $Cmd .= " ".$Opts;
20052 }
20053
20054 chdir($TMP_DIR);
20055 system($Cmd);
20056 chdir($ORIG_DIR);
20057
20058 $Arch = getArch_Object("$TMP_DIR/test");
20059
20060 unlink("$TMP_DIR/test.c");
20061 unlink("$TMP_DIR/test");
20062 }
20063
20064 if(not $Arch) {
20065 exitStatus("Error", "can't check ARCH type");
20066 }
20067
20068 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
20069}
20070
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020071sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020072{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020073 my $LibVersion = $_[0];
20074
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020075 my $Size = undef;
20076
20077 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020078 if(my $Arch = getArch($LibVersion))
20079 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020080 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020081 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020082 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020083 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
20084 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020085 }
20086 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020087
20088 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020089 {
20090 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020091
20092 my $Cmd = $GCC_PATH." -E -dD empty.h";
20093 if(my $Opts = getGCC_Opts($LibVersion))
20094 { # user-defined options
20095 $Cmd .= " ".$Opts;
20096 }
20097
20098 chdir($TMP_DIR);
20099 my $Defines = `$Cmd`;
20100 chdir($ORIG_DIR);
20101
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020102 unlink("$TMP_DIR/empty.h");
20103
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020104 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
20105 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020106 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020107 }
20108 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
20109 { # GCC 3
20110 my $PTRDIFF = $1;
20111 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020112 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020113 }
20114 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020115 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020116 }
20117 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020118 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020119
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020120 if(not $Size) {
20121 exitStatus("Error", "can't check WORD size");
20122 }
20123
20124 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020125}
20126
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020127sub getWordSize($)
20128{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020129 return $WORD_SIZE{$_[0]};
20130}
20131
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020132sub majorVersion($)
20133{
20134 my $V = $_[0];
20135 return 0 if(not $V);
20136 my @VParts = split(/\./, $V);
20137 return $VParts[0];
20138}
20139
20140sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020141{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020142 my ($V1, $V2) = @_;
20143 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020144 my @V1Parts = split(/\./, $V1);
20145 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020146 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20147 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020148 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20149 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20150 }
20151 return -1 if($#V1Parts < $#V2Parts);
20152 return 1 if($#V1Parts > $#V2Parts);
20153 return 0;
20154}
20155
20156sub read_ABI_Dump($$)
20157{
20158 my ($LibVersion, $Path) = @_;
20159 return if(not $LibVersion or not -e $Path);
20160 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020161 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020162 { # input *.abi
20163 $FilePath = $Path;
20164 }
20165 else
20166 { # input *.abi.tar.gz
20167 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020168 if(not isDump_U($FilePath)) {
20169 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20170 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020171 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020172
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020173 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020174
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020175 my $Line = readLineNum($FilePath, 0);
20176 if($Line=~/xml/)
20177 { # XML format
20178 loadModule("XmlDump");
20179 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020180 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020181 else
20182 { # Perl Data::Dumper format (default)
20183 open(DUMP, $FilePath);
20184 local $/ = undef;
20185 my $Content = <DUMP>;
20186 close(DUMP);
20187
20188 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20189 { # remove temp file
20190 unlink($FilePath);
20191 }
20192 if($Content!~/};\s*\Z/) {
20193 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20194 }
20195 $ABI = eval($Content);
20196 if(not $ABI) {
20197 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20198 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020199 }
20200 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020201 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020202 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020203 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020204 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020205 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020206 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020207 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020208
20209 if($ABI->{"ABI_DUMP_VERSION"})
20210 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020211 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020212 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020213 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020214 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020215 }
20216 else
20217 { # support for old ABI dumps
20218 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020219 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020220 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020221 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020222 }
20223 if(majorVersion($DVersion)<2)
20224 { # support for old ABI dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020225 if($UseOldDumps)
20226 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020227 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
20228 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020229 }
20230 }
20231 else
20232 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020233 my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020234 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020235 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020236 }
20237 exitStatus("Dump_Version", $Msg);
20238 }
20239 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020240
20241 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20242 { # DWARF ABI Dump
20243 $UseConv_Real{$LibVersion}{"P"} = 1;
20244 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20245
20246 $UsedDump{$LibVersion}{"DWARF"} = 1;
20247
20248 $TargetComponent = "module";
20249 }
20250
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020251 if(not checkDump($LibVersion, "2.11"))
20252 { # old ABI dumps
20253 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020254 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020255 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020256 { # ABI dump created with --binary option
20257 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20258 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020259 else
20260 { # default
20261 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20262 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020263
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020264 if(defined $ABI->{"Mode"}
20265 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020266 { # --ext option
20267 $ExtendedCheck = 1;
20268 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020269 if($ABI->{"Extra"}) {
20270 $ExtraDump = 1;
20271 }
20272
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020273 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020274 {
20275 $UsedDump{$LibVersion}{"L"} = $Lang;
20276 setLanguage($LibVersion, $Lang);
20277 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020278 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020279 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020280 }
20281 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020282 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020283 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020284 if(not $TInfo)
20285 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020286 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020287 }
20288 my %Tid_TDid = ();
20289 foreach my $TDid (keys(%{$TInfo}))
20290 {
20291 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20292 {
20293 $MAX_ID = $Tid if($Tid>$MAX_ID);
20294 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020295 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020296 }
20297 }
20298 my %NewID = ();
20299 foreach my $Tid (keys(%Tid_TDid))
20300 {
20301 my @TDids = keys(%{$Tid_TDid{$Tid}});
20302 if($#TDids>=1)
20303 {
20304 foreach my $TDid (@TDids)
20305 {
20306 if($TDid) {
20307 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20308 }
20309 else
20310 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020311 my $ID = ++$MAX_ID;
20312
20313 $NewID{$TDid}{$Tid} = $ID;
20314 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20315 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020316 }
20317 }
20318 }
20319 else
20320 {
20321 my $TDid = $TDids[0];
20322 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20323 }
20324 }
20325 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20326 {
20327 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20328 if(defined $Info{"BaseType"})
20329 {
20330 my $Bid = $Info{"BaseType"}{"Tid"};
20331 my $BDid = $Info{"BaseType"}{"TDid"};
20332 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020333 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020334 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20335 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20336 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020337 }
20338 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20339 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020340 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020341 read_Machine_DumpInfo($ABI, $LibVersion);
20342 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020343 if(not $SymbolInfo{$LibVersion})
20344 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020345 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020346 }
20347 if(not keys(%{$SymbolInfo{$LibVersion}}))
20348 { # validation of old-version dumps
20349 if(not $ExtendedCheck) {
20350 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20351 }
20352 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020353 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020354 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020355 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020356 else
20357 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020358 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020359 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020360 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020361 }
20362 if(not $DepSymbols)
20363 { # Cannot reconstruct DepSymbols. This may result in false
20364 # positives if the old dump is for library 2. Not a problem if
20365 # old dumps are only from old libraries.
20366 $DepSymbols = {};
20367 }
20368 foreach my $Symbol (keys(%{$DepSymbols})) {
20369 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20370 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020371 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020372 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020373
20374 if(my $V = $TargetVersion{$LibVersion}) {
20375 $Descriptor{$LibVersion}{"Version"} = $V;
20376 }
20377 else {
20378 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20379 }
20380
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020381 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020382 if(not $SkipTypes{$LibVersion})
20383 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020384 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020385 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020386 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020387 if(not $SkipSymbols{$LibVersion})
20388 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020389 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020390 }
20391 if(not $SkipSymbols{$LibVersion})
20392 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020393 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020394 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020395 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
20396 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20397 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020398 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020399 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020400 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020401 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020402 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020403 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020404 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020405 if(not checkDump($LibVersion, "2.10.1")
20406 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020407 { # support for old ABI dumps: added target headers
20408 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020409 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020410 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020411 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020412 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020413 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020414 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020415 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020416 if(defined $ABI->{"GccConstants"})
20417 { # 3.0
20418 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20419 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20420 }
20421 }
20422
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020423 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020424 if(not $NestedNameSpaces{$LibVersion})
20425 { # support for old dumps
20426 # Cannot reconstruct NameSpaces. This may affect design
20427 # of the compatibility report.
20428 $NestedNameSpaces{$LibVersion} = {};
20429 }
20430 # target system type
20431 # needed to adopt HTML report
20432 if(not $DumpSystem)
20433 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020434 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020435 }
20436 # recreate environment
20437 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20438 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020439 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020440 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020441 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20442 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020443 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020444 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020445 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020446 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20447 {
20448 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20449 setLanguage($LibVersion, "C++");
20450 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020451 }
20452 }
20453 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020454 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20455 {
20456 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20457 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20458 }
20459 }
20460
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020461 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020462 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020463 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020464 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020465 {
20466 if(not $Symbol_Library{$LibVersion}{$MnglName}
20467 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20468 push(@VFunc, $MnglName);
20469 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020470 }
20471 }
20472 translateSymbols(@VFunc, $LibVersion);
20473 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020474 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20475
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020476 if(not checkDump($LibVersion, "3.0"))
20477 { # support for old ABI dumps
20478 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20479 {
20480 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20481 {
20482 if(ref($BaseType) eq "HASH") {
20483 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20484 }
20485 }
20486 }
20487 }
20488
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020489 if(not checkDump($LibVersion, "3.2"))
20490 { # support for old ABI dumps
20491 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20492 {
20493 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20494 {
20495 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20496 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20497 }
20498 }
20499 }
20500
20501 # repair target headers list
20502 delete($TargetHeaders{$LibVersion});
20503 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020504 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20505 }
20506 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20507 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020508 }
20509
20510 # non-target constants from anon enums
20511 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20512 {
20513 if(not $ExtraDump
20514 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20515 {
20516 delete($Constants{$LibVersion}{$Name});
20517 }
20518 }
20519 }
20520
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020521 if(not checkDump($LibVersion, "2.20"))
20522 { # support for old ABI dumps
20523 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20524 {
20525 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20526
20527 if($TType=~/Struct|Union|Enum|Typedef/)
20528 { # repair complex types first
20529 next;
20530 }
20531
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020532 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020533 {
20534 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20535 if($BType=~/Struct|Union|Enum/i)
20536 {
20537 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20538 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20539 }
20540 }
20541 }
20542 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20543 {
20544 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20545 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20546 if($TType=~/Struct|Union|Enum/) {
20547 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20548 }
20549 }
20550 }
20551
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020552 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020553 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020554 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20555 { # support for old ABI dumps < 2.0 (ACC 1.22)
20556 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20557 {
20558 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20559 {
20560 if($Access ne "public") {
20561 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20562 }
20563 }
20564 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20565 }
20566 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20567 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020568 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20569 { # support for old ABI dumps
20570 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20571 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020572 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20573 { # DWARF ABI Dumps
20574 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20575 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020576 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20577 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20578 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020579 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20580 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020581 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020582 foreach (keys(%{$TInfo{"Base"}})) {
20583 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020584 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020585 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020586 if($TInfo{"Type"} eq "MethodPtr")
20587 {
20588 if(defined $TInfo{"Param"})
20589 { # support for old ABI dumps <= 1.17
20590 if(not defined $TInfo{"Param"}{"0"})
20591 {
20592 my $Max = keys(%{$TInfo{"Param"}});
20593 foreach my $Pos (1 .. $Max) {
20594 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20595 }
20596 delete($TInfo{"Param"}{$Max});
20597 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20598 }
20599 }
20600 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020601 if($TInfo{"BaseType"} eq $TypeId)
20602 { # fix ABI dump
20603 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20604 }
20605 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020606 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020607 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020608 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020609 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20610 if(not $BName)
20611 { # broken type
20612 next;
20613 }
20614 if($TInfo{"Name"} eq $BName)
20615 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020616 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020617 next;
20618 }
20619 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20620 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020621 }
20622 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020623 }
20624 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20625 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020626 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020627 }
20628 }
20629
20630 if(not checkDump($LibVersion, "2.15"))
20631 { # support for old ABI dumps
20632 my %Dups = ();
20633 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20634 {
20635 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020636 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020637 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20638 { # remove template decls
20639 delete($SymbolInfo{$LibVersion}{$InfoId});
20640 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020642 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020643 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20644 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020645 { # templates
20646 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020647 }
20648 }
20649 }
20650
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020651 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20652 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020653 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20654 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20655 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20656 { # support for old ABI dumps (< 3.1)
20657 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20658 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20659 { # add "this" first parameter
20660 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20661 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20662
20663 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20664 {
20665 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20666 foreach my $Pos (reverse(0 .. $#Pos)) {
20667 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20668 }
20669 }
20670 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20671 }
20672 }
20673
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020674 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20675 { # ABI dumps have no mangled names for C-functions
20676 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20677 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020678 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20679 { # support for old ABI dumps
20680 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20681 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020682 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20683 { # DWARF ABI Dumps
20684 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20685 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020686 }
20687
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020688 $Descriptor{$LibVersion}{"Dump"} = 1;
20689}
20690
20691sub read_Machine_DumpInfo($$)
20692{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020693 my ($ABI, $LibVersion) = @_;
20694 if($ABI->{"Arch"}) {
20695 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020696 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020697 if($ABI->{"WordSize"}) {
20698 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020699 }
20700 else
20701 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020702 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020703 }
20704 if(not $WORD_SIZE{$LibVersion})
20705 { # support for old dumps (<1.23)
20706 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20707 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020708 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020709 }
20710 else
20711 {
20712 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020713 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020714 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020715 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20716 { # any "pointer"-type
20717 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020718 last;
20719 }
20720 }
20721 if($PSize)
20722 { # a pointer type size
20723 $WORD_SIZE{$LibVersion} = $PSize;
20724 }
20725 else {
20726 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20727 }
20728 }
20729 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020730 if($ABI->{"GccVersion"}) {
20731 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020732 }
20733}
20734
20735sub read_Libs_DumpInfo($$)
20736{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020737 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020738 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20739 if(not $Library_Symbol{$LibVersion})
20740 { # support for old dumps
20741 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20742 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020743 if(keys(%{$Library_Symbol{$LibVersion}})
20744 and not $DumpAPI) {
20745 $Descriptor{$LibVersion}{"Libs"} = "OK";
20746 }
20747}
20748
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020749sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020750{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020751 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020752
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020753 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020754 and not $DumpAPI) {
20755 $Descriptor{$LibVersion}{"Headers"} = "OK";
20756 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020757 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020758 { # headers info is stored in the old dumps in the different way
20759 if($UseOldDumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020760 and my $Name = $ABI->{"Headers"}{$Identity}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020761 { # support for old dumps: headers info corrected in 1.22
20762 $Identity = $Name;
20763 }
20764 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020765 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020766 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020767
20768 if(keys(%{$ABI->{"Sources"}})
20769 and not $DumpAPI) {
20770 $Descriptor{$LibVersion}{"Sources"} = "OK";
20771 }
20772 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
20773 { # headers info is stored in the old dumps in the different way
20774 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20775 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20776 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020777}
20778
20779sub find_libs($$$)
20780{
20781 my ($Path, $Type, $MaxDepth) = @_;
20782 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020783 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020784}
20785
20786sub createDescriptor($$)
20787{
20788 my ($LibVersion, $Path) = @_;
20789 if(not $LibVersion or not $Path
20790 or not -e $Path) {
20791 return "";
20792 }
20793 if(-d $Path)
20794 { # directory with headers files and shared objects
20795 return "
20796 <version>
20797 ".$TargetVersion{$LibVersion}."
20798 </version>
20799
20800 <headers>
20801 $Path
20802 </headers>
20803
20804 <libs>
20805 $Path
20806 </libs>";
20807 }
20808 else
20809 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020810 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020811 { # standard XML-descriptor
20812 return readFile($Path);
20813 }
20814 elsif(is_header($Path, 2, $LibVersion))
20815 { # header file
20816 return "
20817 <version>
20818 ".$TargetVersion{$LibVersion}."
20819 </version>
20820
20821 <headers>
20822 $Path
20823 </headers>
20824
20825 <libs>
20826 none
20827 </libs>";
20828 }
20829 elsif(parse_libname($Path, "name", $OStarget))
20830 { # shared object
20831 return "
20832 <version>
20833 ".$TargetVersion{$LibVersion}."
20834 </version>
20835
20836 <headers>
20837 none
20838 </headers>
20839
20840 <libs>
20841 $Path
20842 </libs>";
20843 }
20844 else
20845 { # standard XML-descriptor
20846 return readFile($Path);
20847 }
20848 }
20849}
20850
20851sub detect_lib_default_paths()
20852{
20853 my %LPaths = ();
20854 if($OSgroup eq "bsd")
20855 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020856 if(my $LdConfig = get_CmdPath("ldconfig"))
20857 {
20858 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20859 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020860 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20861 {
20862 my $Name = "lib".$1;
20863 if(not defined $LPaths{$Name}) {
20864 $LPaths{$Name} = $2;
20865 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020866 }
20867 }
20868 }
20869 else {
20870 printMsg("WARNING", "can't find ldconfig");
20871 }
20872 }
20873 else
20874 {
20875 if(my $LdConfig = get_CmdPath("ldconfig"))
20876 {
20877 if($SystemRoot and $OSgroup eq "linux")
20878 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20879 if(-e $SystemRoot."/etc/ld.so.conf") {
20880 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20881 }
20882 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020883 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20884 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020885 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20886 {
20887 my ($Name, $Path) = ($1, $2);
20888 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020889 if(not defined $LPaths{$Name})
20890 { # get first element from the list of available paths
20891
20892 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20893 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20894 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20895
20896 $LPaths{$Name} = $Path;
20897 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020898 }
20899 }
20900 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020901 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020902 printMsg("WARNING", "can't find ldconfig");
20903 }
20904 }
20905 return \%LPaths;
20906}
20907
20908sub detect_bin_default_paths()
20909{
20910 my $EnvPaths = $ENV{"PATH"};
20911 if($OSgroup eq "beos") {
20912 $EnvPaths.=":".$ENV{"BETOOLS"};
20913 }
20914 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020915 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020916 {
20917 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020918 next if(not $Path);
20919 if($SystemRoot
20920 and $Path=~/\A\Q$SystemRoot\E\//)
20921 { # do NOT use binaries from target system
20922 next;
20923 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020924 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020925 }
20926}
20927
20928sub detect_inc_default_paths()
20929{
20930 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020931 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020932 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020933 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020934 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020935 next if(index($Line, "/cc1plus ")!=-1);
20936
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020937 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20938 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020939 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020940 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020941 if(index($Path, "c++")!=-1
20942 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020943 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020944 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020945 if(not defined $MAIN_CPP_DIR
20946 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20947 $MAIN_CPP_DIR = $Path;
20948 }
20949 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020950 elsif(index($Path, "gcc")!=-1) {
20951 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020952 }
20953 else
20954 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020955 if($Path=~/local[\/\\]+include/)
20956 { # local paths
20957 next;
20958 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020959 if($SystemRoot
20960 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20961 { # The GCC include path for user headers is not a part of the system root
20962 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20963 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20964 next;
20965 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020966 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020967 }
20968 }
20969 }
20970 unlink("$TMP_DIR/empty.h");
20971 return %DPaths;
20972}
20973
20974sub detect_default_paths($)
20975{
20976 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20977 my $Search = $_[0];
20978 if($Search!~/inc/) {
20979 $HSearch = 0;
20980 }
20981 if($Search!~/lib/) {
20982 $LSearch = 0;
20983 }
20984 if($Search!~/bin/) {
20985 $BSearch = 0;
20986 }
20987 if($Search!~/gcc/) {
20988 $GSearch = 0;
20989 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020990 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020991 { # <search_headers> section of the XML descriptor
20992 # do NOT search for systems headers
20993 $HSearch = 0;
20994 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020995 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020996 { # <search_headers> section of the XML descriptor
20997 # do NOT search for systems headers
20998 $LSearch = 0;
20999 }
21000 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
21001 { # additional search paths
21002 next if($Type eq "include" and not $HSearch);
21003 next if($Type eq "lib" and not $LSearch);
21004 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021005 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021006 }
21007 if($OSgroup ne "windows")
21008 { # unix-like
21009 foreach my $Type ("include", "lib", "bin")
21010 { # automatic detection of system "devel" directories
21011 next if($Type eq "include" and not $HSearch);
21012 next if($Type eq "lib" and not $LSearch);
21013 next if($Type eq "bin" and not $BSearch);
21014 my ($UsrDir, $RootDir) = ("/usr", "/");
21015 if($SystemRoot and $Type ne "bin")
21016 { # 1. search for target headers and libraries
21017 # 2. use host commands: ldconfig, readelf, etc.
21018 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
21019 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021020 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021021 if(-d $RootDir."/".$Type)
21022 { # if "/lib" is symbolic link
21023 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021024 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021025 }
21026 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021027 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021028 }
21029 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021030 if(-d $UsrDir)
21031 {
21032 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021033 if(-d $UsrDir."/".$Type)
21034 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021035 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021036 }
21037 }
21038 }
21039 }
21040 if($BSearch)
21041 {
21042 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021043 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021044 }
21045 # check environment variables
21046 if($OSgroup eq "beos")
21047 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021048 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021049 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021050 if($_ eq ".") {
21051 next;
21052 }
21053 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
21054 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
21055 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021056 }
21057 }
21058 if($HSearch)
21059 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021060 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
21061 split(/:|;/, $ENV{"BEINCLUDES"})
21062 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021063 }
21064 if($LSearch)
21065 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021066 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
21067 split(/:|;/, $ENV{"BELIBRARIES"}),
21068 split(/:|;/, $ENV{"LIBRARY_PATH"})
21069 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021070 }
21071 }
21072 if($LSearch)
21073 { # using linker to get system paths
21074 if(my $LPaths = detect_lib_default_paths())
21075 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021076 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021077 foreach my $Name (keys(%{$LPaths}))
21078 {
21079 if($SystemRoot
21080 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
21081 { # wrong ldconfig configuration
21082 # check your <sysroot>/etc/ld.so.conf
21083 next;
21084 }
21085 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021086 if(my $Dir = get_dirname($LPaths->{$Name})) {
21087 $Dirs{$Dir} = 1;
21088 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021089 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021090 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021091 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021092 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021093 }
21094 if($BSearch)
21095 {
21096 if($CrossGcc)
21097 { # --cross-gcc=arm-linux-gcc
21098 if(-e $CrossGcc)
21099 { # absolute or relative path
21100 $GCC_PATH = get_abs_path($CrossGcc);
21101 }
21102 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
21103 { # command name
21104 $GCC_PATH = $CrossGcc;
21105 }
21106 else {
21107 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
21108 }
21109 if($GCC_PATH=~/\s/) {
21110 $GCC_PATH = "\"".$GCC_PATH."\"";
21111 }
21112 }
21113 }
21114 if($GSearch)
21115 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021116 if(not $CrossGcc)
21117 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021118 $GCC_PATH = get_CmdPath("gcc");
21119 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021120 if(not $GCC_PATH)
21121 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021122 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021123 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021124 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021125 { # select the latest version
21126 @GCCs = sort {$b cmp $a} @GCCs;
21127 if(check_gcc($GCCs[0], "3"))
21128 {
21129 $GCC_PATH = $GCCs[0];
21130 last;
21131 }
21132 }
21133 }
21134 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021135 if(not $GCC_PATH) {
21136 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21137 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021138
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021139 if(not $CheckObjectsOnly_Opt)
21140 {
21141 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
21142 {
21143 my $GccTarget = get_dumpmachine($GCC_PATH);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040021144 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021145 if($GccTarget=~/symbian/)
21146 {
21147 $OStarget = "symbian";
21148 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21149 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021150
21151 # check GCC version
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040021152 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021153 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040021154 # introduced in 4.8
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040021155 # fixed in 4.8.3
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021156 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
21157 $EMERGENCY_MODE_48 = 1;
21158 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021159 }
21160 else {
21161 exitStatus("Error", "something is going wrong with the GCC compiler");
21162 }
21163 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021164 if($HSearch)
21165 {
21166 if(not $NoStdInc)
21167 { # do NOT search in GCC standard paths
21168 my %DPaths = detect_inc_default_paths();
21169 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21170 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21171 @DefaultIncPaths = @{$DPaths{"Inc"}};
21172 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021173 }
21174 }
21175 }
21176 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021177 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021178 my $IncPath = "/usr/include";
21179 if($SystemRoot) {
21180 $IncPath = $SystemRoot.$IncPath;
21181 }
21182 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021183 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021184 }
21185 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021186
21187 if($ExtraInfo)
21188 {
21189 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21190 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21191 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021192}
21193
21194sub getLIB_EXT($)
21195{
21196 my $Target = $_[0];
21197 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21198 return $Ext;
21199 }
21200 return $OS_LibExt{$LIB_TYPE}{"default"};
21201}
21202
21203sub getAR_EXT($)
21204{
21205 my $Target = $_[0];
21206 if(my $Ext = $OS_Archive{$Target}) {
21207 return $Ext;
21208 }
21209 return $OS_Archive{"default"};
21210}
21211
21212sub get_dumpversion($)
21213{
21214 my $Cmd = $_[0];
21215 return "" if(not $Cmd);
21216 if($Cache{"get_dumpversion"}{$Cmd}) {
21217 return $Cache{"get_dumpversion"}{$Cmd};
21218 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021219 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021220 chomp($V);
21221 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21222}
21223
21224sub get_dumpmachine($)
21225{
21226 my $Cmd = $_[0];
21227 return "" if(not $Cmd);
21228 if($Cache{"get_dumpmachine"}{$Cmd}) {
21229 return $Cache{"get_dumpmachine"}{$Cmd};
21230 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021231 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021232 chomp($Machine);
21233 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21234}
21235
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021236sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021237{
21238 my $Cmd = $_[0];
21239 return "" if(not $Cmd);
21240 my @Options = (
21241 "--version",
21242 "-help"
21243 );
21244 foreach my $Opt (@Options)
21245 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021246 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021247 if($Info) {
21248 return 1;
21249 }
21250 }
21251 return 0;
21252}
21253
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021254sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021255{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021256 my ($Cmd, $ReqVer) = @_;
21257 return 0 if(not $Cmd or not $ReqVer);
21258 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21259 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021260 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021261 if(my $GccVer = get_dumpversion($Cmd))
21262 {
21263 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21264 if(cmpVersions($GccVer, $ReqVer)>=0) {
21265 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21266 }
21267 }
21268 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021269}
21270
21271sub get_depth($)
21272{
21273 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021274 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021275 }
21276 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21277}
21278
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021279sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021280{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021281 return if($Cache{"registerGccHeaders"}); # this function should be called once
21282
21283 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021284 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021285 my @Headers = cmd_find($Path,"f");
21286 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21287 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021288 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021289 my $FileName = get_filename($HPath);
21290 if(not defined $DefaultGccHeader{$FileName})
21291 { # skip duplicated
21292 $DefaultGccHeader{$FileName} = $HPath;
21293 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021294 }
21295 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021296 $Cache{"registerGccHeaders"} = 1;
21297}
21298
21299sub registerCppHeaders()
21300{
21301 return if($Cache{"registerCppHeaders"}); # this function should be called once
21302
21303 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021304 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021305 my @Headers = cmd_find($CppDir,"f");
21306 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21307 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021308 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021309 my $FileName = get_filename($Path);
21310 if(not defined $DefaultCppHeader{$FileName})
21311 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021312 $DefaultCppHeader{$FileName} = $Path;
21313 }
21314 }
21315 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021316 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021317}
21318
21319sub parse_libname($$$)
21320{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021321 return "" if(not $_[0]);
21322 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21323 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021324 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021325 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21326}
21327
21328sub parse_libname_I($$$)
21329{
21330 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021331
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021332 if($Target eq "symbian") {
21333 return parse_libname_symbian($Name, $Type);
21334 }
21335 elsif($Target eq "windows") {
21336 return parse_libname_windows($Name, $Type);
21337 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021338
21339 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021340 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021341 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021342 { # libSDL-1.2.so.0.7.1
21343 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021344 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021345 if($Type eq "name")
21346 { # libSDL-1.2
21347 # libwbxml2
21348 return $2;
21349 }
21350 elsif($Type eq "name+ext")
21351 { # libSDL-1.2.so
21352 # libwbxml2.so
21353 return $1;
21354 }
21355 elsif($Type eq "version")
21356 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021357 if(defined $7
21358 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021359 { # 0.7.1
21360 return $7;
21361 }
21362 else
21363 { # libc-2.5.so (=>2.5 version)
21364 my $MV = $5;
21365 $MV=~s/\A[\-\_]+//g;
21366 return $MV;
21367 }
21368 }
21369 elsif($Type eq "short")
21370 { # libSDL
21371 # libwbxml2
21372 return $3;
21373 }
21374 elsif($Type eq "shortest")
21375 { # SDL
21376 # wbxml
21377 return shortest_name($3);
21378 }
21379 }
21380 return "";# error
21381}
21382
21383sub parse_libname_symbian($$)
21384{
21385 my ($Name, $Type) = @_;
21386 my $Ext = getLIB_EXT("symbian");
21387 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21388 { # libpthread{00010001}.dso
21389 if($Type eq "name")
21390 { # libpthread{00010001}
21391 return $2;
21392 }
21393 elsif($Type eq "name+ext")
21394 { # libpthread{00010001}.dso
21395 return $1;
21396 }
21397 elsif($Type eq "version")
21398 { # 00010001
21399 my $V = $4;
21400 $V=~s/\{(.+)\}/$1/;
21401 return $V;
21402 }
21403 elsif($Type eq "short")
21404 { # libpthread
21405 return $3;
21406 }
21407 elsif($Type eq "shortest")
21408 { # pthread
21409 return shortest_name($3);
21410 }
21411 }
21412 return "";# error
21413}
21414
21415sub parse_libname_windows($$)
21416{
21417 my ($Name, $Type) = @_;
21418 my $Ext = getLIB_EXT("windows");
21419 if($Name=~/((.+?)\.$Ext)\Z/)
21420 { # netapi32.dll
21421 if($Type eq "name")
21422 { # netapi32
21423 return $2;
21424 }
21425 elsif($Type eq "name+ext")
21426 { # netapi32.dll
21427 return $1;
21428 }
21429 elsif($Type eq "version")
21430 { # DLL version embedded
21431 # at binary-level
21432 return "";
21433 }
21434 elsif($Type eq "short")
21435 { # netapi32
21436 return $2;
21437 }
21438 elsif($Type eq "shortest")
21439 { # netapi
21440 return shortest_name($2);
21441 }
21442 }
21443 return "";# error
21444}
21445
21446sub shortest_name($)
21447{
21448 my $Name = $_[0];
21449 # remove prefix
21450 $Name=~s/\A(lib|open)//;
21451 # remove suffix
21452 $Name=~s/[\W\d_]+\Z//i;
21453 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21454 return $Name;
21455}
21456
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021457sub createSymbolsList($$$$$)
21458{
21459 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
21460 read_ABI_Dump(1, $DPath);
21461 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021462 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021463 }
21464 my %SymbolHeaderLib = ();
21465 my $Total = 0;
21466 # Get List
21467 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21468 {
21469 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021470 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021471 next;
21472 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021473 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021474 { # skip other symbols
21475 next;
21476 }
21477 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21478 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021479 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021480 next;
21481 }
21482 my $DyLib = $Symbol_Library{1}{$Symbol};
21483 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021484 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021485 next;
21486 }
21487 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21488 $Total+=1;
21489 }
21490 # Draw List
21491 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21492 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21493 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21494 {
21495 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21496 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021497 my %NS_Symbol = ();
21498 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021499 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021500 }
21501 foreach my $NameSpace (sort keys(%NS_Symbol))
21502 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021503 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021504 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21505 foreach my $Symbol (@SortedInterfaces)
21506 {
21507 my $SubReport = "";
21508 my $Signature = get_Signature($Symbol, 1);
21509 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021510 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021511 }
21512 if($Symbol=~/\A(_Z|\?)/)
21513 {
21514 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021515 $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 +040021516 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021517 else {
21518 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21519 }
21520 }
21521 else
21522 {
21523 if($Signature) {
21524 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21525 }
21526 else {
21527 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21528 }
21529 }
21530 $SYMBOLS_LIST .= $SubReport;
21531 }
21532 }
21533 $SYMBOLS_LIST .= "<br/>\n";
21534 }
21535 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021536 # clear info
21537 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21538 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21539 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21540 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021541 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021542 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021543 my $CssStyles = readModule("Styles", "SymbolsList.css");
21544 my $JScripts = readModule("Scripts", "Sections.js");
21545 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021546 my $Title = "$LName: public symbols";
21547 my $Keywords = "$LName, API, symbols";
21548 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021549 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021550 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021551 <br/><br/><hr/>\n".getReportFooter($LName, 1)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021552 <div style='height:999px;'></div></body></html>";
21553 writeFile($SaveTo, $SYMBOLS_LIST);
21554}
21555
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021556sub add_target_libs($)
21557{
21558 foreach (@{$_[0]}) {
21559 $TargetLibs{$_} = 1;
21560 }
21561}
21562
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021563sub is_target_lib($)
21564{
21565 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021566 if(not $LName) {
21567 return 0;
21568 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021569 if($TargetLibraryName
21570 and $LName!~/\Q$TargetLibraryName\E/) {
21571 return 0;
21572 }
21573 if(keys(%TargetLibs)
21574 and not $TargetLibs{$LName}
21575 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21576 return 0;
21577 }
21578 return 1;
21579}
21580
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021581sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021582{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021583 my ($H, $V) = @_;
21584 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021585 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021586 if($TargetHeaders{$V}{$H}) {
21587 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021588 }
21589 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021590 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021591}
21592
21593sub checkVersionNum($$)
21594{
21595 my ($LibVersion, $Path) = @_;
21596 if(my $VerNum = $TargetVersion{$LibVersion}) {
21597 return $VerNum;
21598 }
21599 my $UsedAltDescr = 0;
21600 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021601 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021602 next if(isDump($Part)); # ABI dump
21603 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021604 my $VerNum = "";
21605 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021606 {
21607 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021608 $VerNum = parse_libname($Part, "version", $OStarget);
21609 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021610 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021611 }
21612 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021613 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
21614 {
21615 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021616 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021617 }
21618 if($VerNum ne "")
21619 {
21620 $TargetVersion{$LibVersion} = $VerNum;
21621 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021622 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021623 }
21624 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021625 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 +040021626 }
21627 return $TargetVersion{$LibVersion};
21628 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021629 }
21630 if($UsedAltDescr)
21631 {
21632 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021633 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021634 }
21635 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021636 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021637 }
21638 }
21639}
21640
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021641sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021642{
21643 my $Str = $_[0];
21644 return "" if(not $Str);
21645 $Str=~s/\Q$TargetLibraryName\E//g;
21646 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021647 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021648 return $2;
21649 }
21650 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
21651 return $V;
21652 }
21653 return "";
21654}
21655
21656sub readLibs($)
21657{
21658 my $LibVersion = $_[0];
21659 if($OStarget eq "windows")
21660 { # dumpbin.exe will crash
21661 # without VS Environment
21662 check_win32_env();
21663 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021664 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021665 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021666 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021667}
21668
21669sub dump_sorting($)
21670{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021671 my $Hash = $_[0];
21672 return [] if(not $Hash);
21673 my @Keys = keys(%{$Hash});
21674 return [] if($#Keys<0);
21675 if($Keys[0]=~/\A\d+\Z/)
21676 { # numbers
21677 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021678 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021679 else
21680 { # strings
21681 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021682 }
21683}
21684
21685sub printMsg($$)
21686{
21687 my ($Type, $Msg) = @_;
21688 if($Type!~/\AINFO/) {
21689 $Msg = $Type.": ".$Msg;
21690 }
21691 if($Type!~/_C\Z/) {
21692 $Msg .= "\n";
21693 }
21694 if($Quiet)
21695 { # --quiet option
21696 appendFile($COMMON_LOG_PATH, $Msg);
21697 }
21698 else
21699 {
21700 if($Type eq "ERROR") {
21701 print STDERR $Msg;
21702 }
21703 else {
21704 print $Msg;
21705 }
21706 }
21707}
21708
21709sub exitStatus($$)
21710{
21711 my ($Code, $Msg) = @_;
21712 printMsg("ERROR", $Msg);
21713 exit($ERROR_CODE{$Code});
21714}
21715
21716sub exitReport()
21717{ # the tool has run without any errors
21718 printReport();
21719 if($COMPILE_ERRORS)
21720 { # errors in headers may add false positives/negatives
21721 exit($ERROR_CODE{"Compile_Error"});
21722 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021723 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21724 { # --binary
21725 exit($ERROR_CODE{"Incompatible"});
21726 }
21727 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21728 { # --source
21729 exit($ERROR_CODE{"Incompatible"});
21730 }
21731 elsif($RESULT{"Source"}{"Problems"}
21732 or $RESULT{"Binary"}{"Problems"})
21733 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021734 exit($ERROR_CODE{"Incompatible"});
21735 }
21736 else {
21737 exit($ERROR_CODE{"Compatible"});
21738 }
21739}
21740
21741sub readRules($)
21742{
21743 my $Kind = $_[0];
21744 if(not -f $RULES_PATH{$Kind}) {
21745 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21746 }
21747 my $Content = readFile($RULES_PATH{$Kind});
21748 while(my $Rule = parseTag(\$Content, "rule"))
21749 {
21750 my $RId = parseTag(\$Rule, "id");
21751 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21752 foreach my $Prop (@Properties) {
21753 if(my $Value = parseTag(\$Rule, lc($Prop)))
21754 {
21755 $Value=~s/\n[ ]*//;
21756 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21757 }
21758 }
21759 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21760 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21761 }
21762 else {
21763 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21764 }
21765 }
21766}
21767
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021768sub getReportPath($)
21769{
21770 my $Level = $_[0];
21771 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21772 if($Level eq "Binary")
21773 {
21774 if($BinaryReportPath)
21775 { # --bin-report-path
21776 return $BinaryReportPath;
21777 }
21778 elsif($OutputReportPath)
21779 { # --report-path
21780 return $OutputReportPath;
21781 }
21782 else
21783 { # default
21784 return $Dir."/abi_compat_report.$ReportFormat";
21785 }
21786 }
21787 elsif($Level eq "Source")
21788 {
21789 if($SourceReportPath)
21790 { # --src-report-path
21791 return $SourceReportPath;
21792 }
21793 elsif($OutputReportPath)
21794 { # --report-path
21795 return $OutputReportPath;
21796 }
21797 else
21798 { # default
21799 return $Dir."/src_compat_report.$ReportFormat";
21800 }
21801 }
21802 else
21803 {
21804 if($OutputReportPath)
21805 { # --report-path
21806 return $OutputReportPath;
21807 }
21808 else
21809 { # default
21810 return $Dir."/compat_report.$ReportFormat";
21811 }
21812 }
21813}
21814
21815sub printStatMsg($)
21816{
21817 my $Level = $_[0];
21818 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21819}
21820
21821sub listAffected($)
21822{
21823 my $Level = $_[0];
21824 my $List = "";
21825 foreach (keys(%{$TotalAffected{$Level}}))
21826 {
21827 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21828 { # skip "Low"-severity problems
21829 next;
21830 }
21831 $List .= "$_\n";
21832 }
21833 my $Dir = get_dirname(getReportPath($Level));
21834 if($Level eq "Binary") {
21835 writeFile($Dir."/abi_affected.txt", $List);
21836 }
21837 elsif($Level eq "Source") {
21838 writeFile($Dir."/src_affected.txt", $List);
21839 }
21840}
21841
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021842sub printReport()
21843{
21844 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021845 createReport();
21846 if($JoinReport or $DoubleReport)
21847 {
21848 if($RESULT{"Binary"}{"Problems"}
21849 or $RESULT{"Source"}{"Problems"}) {
21850 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021851 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021852 else {
21853 printMsg("INFO", "result: COMPATIBLE");
21854 }
21855 printStatMsg("Binary");
21856 printStatMsg("Source");
21857 if($ListAffected)
21858 { # --list-affected
21859 listAffected("Binary");
21860 listAffected("Source");
21861 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021862 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021863 elsif($BinaryOnly)
21864 {
21865 if($RESULT{"Binary"}{"Problems"}) {
21866 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21867 }
21868 else {
21869 printMsg("INFO", "result: COMPATIBLE");
21870 }
21871 printStatMsg("Binary");
21872 if($ListAffected)
21873 { # --list-affected
21874 listAffected("Binary");
21875 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021876 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021877 elsif($SourceOnly)
21878 {
21879 if($RESULT{"Source"}{"Problems"}) {
21880 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21881 }
21882 else {
21883 printMsg("INFO", "result: COMPATIBLE");
21884 }
21885 printStatMsg("Source");
21886 if($ListAffected)
21887 { # --list-affected
21888 listAffected("Source");
21889 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021890 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021891 if($StdOut)
21892 {
21893 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021894 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021895 printMsg("INFO", "compatibility report has been generated to stdout");
21896 }
21897 else
21898 { # default
21899 printMsg("INFO", "compatibility reports have been generated to stdout");
21900 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021901 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021902 else
21903 {
21904 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021905 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021906 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21907 }
21908 elsif($DoubleReport)
21909 { # default
21910 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21911 }
21912 elsif($BinaryOnly)
21913 { # --binary
21914 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21915 }
21916 elsif($SourceOnly)
21917 { # --source
21918 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21919 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021920 }
21921}
21922
21923sub check_win32_env()
21924{
21925 if(not $ENV{"DevEnvDir"}
21926 or not $ENV{"LIB"}) {
21927 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21928 }
21929}
21930
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021931sub diffSets($$)
21932{
21933 my ($S1, $S2) = @_;
21934 my @SK1 = keys(%{$S1});
21935 my @SK2 = keys(%{$S2});
21936 if($#SK1!=$#SK2) {
21937 return 1;
21938 }
21939 foreach my $K1 (@SK1)
21940 {
21941 if(not defined $S2->{$K1}) {
21942 return 1;
21943 }
21944 }
21945 return 0;
21946}
21947
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021948sub create_ABI_Dump()
21949{
21950 if(not -e $DumpAPI) {
21951 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21952 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021953
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021954 my @DParts = split(/\s*,\s*/, $DumpAPI);
21955 foreach my $Part (@DParts)
21956 {
21957 if(not -e $Part) {
21958 exitStatus("Access_Error", "can't access \'$Part\'");
21959 }
21960 }
21961 checkVersionNum(1, $DumpAPI);
21962 foreach my $Part (@DParts)
21963 {
21964 if(isDump($Part)) {
21965 read_ABI_Dump(1, $Part);
21966 }
21967 else {
21968 readDescriptor(1, createDescriptor(1, $Part));
21969 }
21970 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021971
21972 if(not $Descriptor{1}{"Version"})
21973 { # set to default: X
21974 $Descriptor{1}{"Version"} = "X";
21975 }
21976
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021977 initLogging(1);
21978 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021979
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021980 my $DumpPath = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi";
21981 $DumpPath .= ".".$AR_EXT; # gzipped by default
21982 if($OutputDumpPath)
21983 { # user defined path
21984 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021985 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021986 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21987
21988 if(not $Archive and not $StdOut)
21989 { # check archive utilities
21990 if($OSgroup eq "windows")
21991 { # using zip
21992 my $ZipCmd = get_CmdPath("zip");
21993 if(not $ZipCmd) {
21994 exitStatus("Not_Found", "can't find \"zip\"");
21995 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021996 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021997 else
21998 { # using tar and gzip
21999 my $TarCmd = get_CmdPath("tar");
22000 if(not $TarCmd) {
22001 exitStatus("Not_Found", "can't find \"tar\"");
22002 }
22003 my $GzipCmd = get_CmdPath("gzip");
22004 if(not $GzipCmd) {
22005 exitStatus("Not_Found", "can't find \"gzip\"");
22006 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022007 }
22008 }
22009
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022010 if(not $Descriptor{1}{"Dump"})
22011 {
22012 if(not $CheckHeadersOnly) {
22013 readLibs(1);
22014 }
22015 if($CheckHeadersOnly) {
22016 setLanguage(1, "C++");
22017 }
22018 if(not $CheckObjectsOnly) {
22019 searchForHeaders(1);
22020 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022021 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022022 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022023 if(not $Descriptor{1}{"Dump"})
22024 {
22025 if($Descriptor{1}{"Headers"}) {
22026 readHeaders(1);
22027 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022028 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022029 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022030 if(not keys(%{$SymbolInfo{1}}))
22031 { # check if created dump is valid
22032 if(not $ExtendedCheck and not $CheckObjectsOnly)
22033 {
22034 if($CheckHeadersOnly) {
22035 exitStatus("Empty_Set", "the set of public symbols is empty");
22036 }
22037 else {
22038 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
22039 }
22040 }
22041 }
22042 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022043 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022044 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
22045 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022046 if($ExtraDump)
22047 { # add unmangled names to the ABI dump
22048 my @Names = ();
22049 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22050 {
22051 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
22052 push(@Names, $MnglName);
22053 }
22054 }
22055 translateSymbols(@Names, 1);
22056 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22057 {
22058 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
22059 {
22060 if(my $Unmangled = $tr_name{$MnglName})
22061 {
22062 if($MnglName ne $Unmangled) {
22063 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
22064 }
22065 }
22066 }
22067 }
22068 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022069
22070 my %GccConstants = (); # built-in GCC constants
22071 foreach my $Name (keys(%{$Constants{1}}))
22072 {
22073 if(not defined $Constants{1}{$Name}{"Header"})
22074 {
22075 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
22076 delete($Constants{1}{$Name});
22077 }
22078 }
22079
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022080 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022081 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022082 "TypeInfo" => $TypeInfo{1},
22083 "SymbolInfo" => $SymbolInfo{1},
22084 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022085 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022086 "SymbolVersion" => $SymVer{1},
22087 "LibraryVersion" => $Descriptor{1}{"Version"},
22088 "LibraryName" => $TargetLibraryName,
22089 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022090 "SkipTypes" => $SkipTypes{1},
22091 "SkipSymbols" => $SkipSymbols{1},
22092 "SkipNameSpaces" => $SkipNameSpaces{1},
22093 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022094 "Headers" => \%HeadersInfo,
22095 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022096 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022097 "NameSpaces" => $NestedNameSpaces{1},
22098 "Target" => $OStarget,
22099 "Arch" => getArch(1),
22100 "WordSize" => $WORD_SIZE{1},
22101 "GccVersion" => get_dumpversion($GCC_PATH),
22102 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
22103 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
22104 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022105 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022106 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022107 }
22108 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022109 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022110 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022111 if($ExtendedCheck)
22112 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022113 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022114 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022115 if($BinaryOnly)
22116 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022117 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022118 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022119 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022120 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022121 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022122 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
22123 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022124 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022125
22126 my $ABI_DUMP = "";
22127 if($UseXML)
22128 {
22129 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022130 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022131 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022132 else
22133 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022134 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022135 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022136 if($StdOut)
22137 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022138 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022139 printMsg("INFO", "ABI dump has been generated to stdout");
22140 return;
22141 }
22142 else
22143 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022144 my ($DDir, $DName) = separate_path($DumpPath);
22145 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022146 if(not $Archive) {
22147 $DPath = $DumpPath;
22148 }
22149
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022150 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022151
22152 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022153 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022154 close(DUMP);
22155
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022156 if(not -s $DPath) {
22157 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
22158 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022159 if($Archive) {
22160 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022161 }
22162
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022163 if($OutputDumpPath) {
22164 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022165 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022166 else {
22167 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
22168 }
22169 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 +040022170 }
22171}
22172
22173sub quickEmptyReports()
22174{ # Quick "empty" reports
22175 # 4 times faster than merging equal dumps
22176 # NOTE: the dump contains the "LibraryVersion" attribute
22177 # if you change the version, then your dump will be different
22178 # OVERCOME: use -v1 and v2 options for comparing dumps
22179 # and don't change version in the XML descriptor (and dumps)
22180 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
22181 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
22182 {
22183 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
22184 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
22185 if($FilePath1 and $FilePath2)
22186 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022187 my $Line = readLineNum($FilePath1, 0);
22188 if($Line=~/xml/)
22189 { # XML format
22190 # is not supported yet
22191 return;
22192 }
22193
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022194 local $/ = undef;
22195
22196 open(DUMP1, $FilePath1);
22197 my $Content1 = <DUMP1>;
22198 close(DUMP1);
22199
22200 open(DUMP2, $FilePath2);
22201 my $Content2 = <DUMP2>;
22202 close(DUMP2);
22203
22204 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022205 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022206 # clean memory
22207 undef $Content2;
22208
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022209 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022210 my $ABIdump = eval($Content1);
22211
22212 # clean memory
22213 undef $Content1;
22214
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022215 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022216 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 +040022217 }
22218 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022219 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022220 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22221 }
22222 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022223 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022224 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22225 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022226 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022227 read_Libs_DumpInfo($ABIdump, 1);
22228 read_Machine_DumpInfo($ABIdump, 1);
22229 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022230
22231 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22232 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22233
22234 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
22235 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
22236
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022237 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22238 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
22239 exitReport();
22240 }
22241 }
22242 }
22243}
22244
22245sub initLogging($)
22246{
22247 my $LibVersion = $_[0];
22248 # create log directory
22249 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22250 if($OutputLogPath{$LibVersion})
22251 { # user-defined by -log-path option
22252 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22253 }
22254 if($LogMode ne "n") {
22255 mkpath($LOG_DIR);
22256 }
22257 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022258 if($Debug)
22259 { # debug directory
22260 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022261
22262 if(not $ExtraInfo)
22263 { # enable --extra-info
22264 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22265 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022266 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022267 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022268}
22269
22270sub writeLog($$)
22271{
22272 my ($LibVersion, $Msg) = @_;
22273 if($LogMode ne "n") {
22274 appendFile($LOG_PATH{$LibVersion}, $Msg);
22275 }
22276}
22277
22278sub resetLogging($)
22279{
22280 my $LibVersion = $_[0];
22281 if($LogMode!~/a|n/)
22282 { # remove old log
22283 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022284 if($Debug) {
22285 rmtree($DEBUG_PATH{$LibVersion});
22286 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022287 }
22288}
22289
22290sub printErrorLog($)
22291{
22292 my $LibVersion = $_[0];
22293 if($LogMode ne "n") {
22294 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22295 }
22296}
22297
22298sub isDump($)
22299{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022300 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22301 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022302 return $1;
22303 }
22304 return 0;
22305}
22306
22307sub isDump_U($)
22308{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022309 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022310 return $1;
22311 }
22312 return 0;
22313}
22314
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022315sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022316{
22317 # read input XML descriptors or ABI dumps
22318 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022319 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022320 }
22321 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
22322 foreach my $Part (@DParts1)
22323 {
22324 if(not -e $Part) {
22325 exitStatus("Access_Error", "can't access \'$Part\'");
22326 }
22327 }
22328 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022329 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022330 }
22331 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
22332 foreach my $Part (@DParts2)
22333 {
22334 if(not -e $Part) {
22335 exitStatus("Access_Error", "can't access \'$Part\'");
22336 }
22337 }
22338 detect_default_paths("bin"); # to extract dumps
22339 if($#DParts1==0 and $#DParts2==0
22340 and isDump($Descriptor{1}{"Path"})
22341 and isDump($Descriptor{2}{"Path"}))
22342 { # optimization: equal ABI dumps
22343 quickEmptyReports();
22344 }
22345 checkVersionNum(1, $Descriptor{1}{"Path"});
22346 checkVersionNum(2, $Descriptor{2}{"Path"});
22347 printMsg("INFO", "preparation, please wait ...");
22348 foreach my $Part (@DParts1)
22349 {
22350 if(isDump($Part)) {
22351 read_ABI_Dump(1, $Part);
22352 }
22353 else {
22354 readDescriptor(1, createDescriptor(1, $Part));
22355 }
22356 }
22357 foreach my $Part (@DParts2)
22358 {
22359 if(isDump($Part)) {
22360 read_ABI_Dump(2, $Part);
22361 }
22362 else {
22363 readDescriptor(2, createDescriptor(2, $Part));
22364 }
22365 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022366
22367 if(not $Descriptor{1}{"Version"})
22368 { # set to default: X
22369 $Descriptor{1}{"Version"} = "X";
22370 }
22371
22372 if(not $Descriptor{2}{"Version"})
22373 { # set to default: Y
22374 $Descriptor{2}{"Version"} = "Y";
22375 }
22376
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022377 initLogging(1);
22378 initLogging(2);
22379 # check consistency
22380 if(not $Descriptor{1}{"Headers"}
22381 and not $Descriptor{1}{"Libs"}) {
22382 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
22383 }
22384 if(not $Descriptor{2}{"Headers"}
22385 and not $Descriptor{2}{"Libs"}) {
22386 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
22387 }
22388 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
22389 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
22390 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
22391 }
22392 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
22393 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
22394 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
22395 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022396 if(not $Descriptor{1}{"Headers"})
22397 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022398 if($CheckHeadersOnly_Opt) {
22399 exitStatus("Error", "can't find header files info in descriptor d1");
22400 }
22401 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022402 if(not $Descriptor{2}{"Headers"})
22403 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022404 if($CheckHeadersOnly_Opt) {
22405 exitStatus("Error", "can't find header files info in descriptor d2");
22406 }
22407 }
22408 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022409 or not $Descriptor{2}{"Headers"})
22410 {
22411 if(not $CheckObjectsOnly_Opt)
22412 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022413 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
22414 $CheckObjectsOnly = 1;
22415 }
22416 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022417 if(not $Descriptor{1}{"Libs"})
22418 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022419 if($CheckObjectsOnly_Opt) {
22420 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
22421 }
22422 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022423 if(not $Descriptor{2}{"Libs"})
22424 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022425 if($CheckObjectsOnly_Opt) {
22426 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
22427 }
22428 }
22429 if(not $Descriptor{1}{"Libs"}
22430 or not $Descriptor{2}{"Libs"})
22431 { # comparing standalone header files
22432 # comparing ABI dumps created with --headers-only
22433 if(not $CheckHeadersOnly_Opt)
22434 {
22435 printMsg("WARNING", "checking headers only");
22436 $CheckHeadersOnly = 1;
22437 }
22438 }
22439 if($UseDumps)
22440 { # --use-dumps
22441 # parallel processing
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022442 my $DumpPath1 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi.$AR_EXT";
22443 my $DumpPath2 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{2}{"Version"}.".abi.$AR_EXT";
22444
22445 unlink($DumpPath1);
22446 unlink($DumpPath2);
22447
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022448 my $pid = fork();
22449 if($pid)
22450 { # dump on two CPU cores
22451 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22452 if($RelativeDirectory{1}) {
22453 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22454 }
22455 if($OutputLogPath{1}) {
22456 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22457 }
22458 if($CrossGcc) {
22459 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22460 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022461 if($Quiet)
22462 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022463 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022464 @PARAMS = (@PARAMS, "-logging-mode", "a");
22465 }
22466 elsif($LogMode and $LogMode ne "w")
22467 { # "w" is default
22468 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022469 }
22470 if($ExtendedCheck) {
22471 @PARAMS = (@PARAMS, "-extended");
22472 }
22473 if($UserLang) {
22474 @PARAMS = (@PARAMS, "-lang", $UserLang);
22475 }
22476 if($TargetVersion{1}) {
22477 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22478 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022479 if($BinaryOnly) {
22480 @PARAMS = (@PARAMS, "-binary");
22481 }
22482 if($SourceOnly) {
22483 @PARAMS = (@PARAMS, "-source");
22484 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022485 if($SortDump) {
22486 @PARAMS = (@PARAMS, "-sort");
22487 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022488 if($DumpFormat and $DumpFormat ne "perl") {
22489 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22490 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022491 if($CheckHeadersOnly) {
22492 @PARAMS = (@PARAMS, "-headers-only");
22493 }
22494 if($CheckObjectsOnly) {
22495 @PARAMS = (@PARAMS, "-objects-only");
22496 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022497 if($Debug)
22498 {
22499 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022500 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022501 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022502 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022503 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022504 exit(1);
22505 }
22506 }
22507 else
22508 { # child
22509 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22510 if($RelativeDirectory{2}) {
22511 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22512 }
22513 if($OutputLogPath{2}) {
22514 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22515 }
22516 if($CrossGcc) {
22517 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22518 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022519 if($Quiet)
22520 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022521 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022522 @PARAMS = (@PARAMS, "-logging-mode", "a");
22523 }
22524 elsif($LogMode and $LogMode ne "w")
22525 { # "w" is default
22526 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022527 }
22528 if($ExtendedCheck) {
22529 @PARAMS = (@PARAMS, "-extended");
22530 }
22531 if($UserLang) {
22532 @PARAMS = (@PARAMS, "-lang", $UserLang);
22533 }
22534 if($TargetVersion{2}) {
22535 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22536 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022537 if($BinaryOnly) {
22538 @PARAMS = (@PARAMS, "-binary");
22539 }
22540 if($SourceOnly) {
22541 @PARAMS = (@PARAMS, "-source");
22542 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022543 if($SortDump) {
22544 @PARAMS = (@PARAMS, "-sort");
22545 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022546 if($DumpFormat and $DumpFormat ne "perl") {
22547 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22548 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022549 if($CheckHeadersOnly) {
22550 @PARAMS = (@PARAMS, "-headers-only");
22551 }
22552 if($CheckObjectsOnly) {
22553 @PARAMS = (@PARAMS, "-objects-only");
22554 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022555 if($Debug)
22556 {
22557 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022558 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022559 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022560 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022561 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022562 exit(1);
22563 }
22564 else {
22565 exit(0);
22566 }
22567 }
22568 waitpid($pid, 0);
22569 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022570 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22571 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022572 if($TargetLibraryFName ne $TargetLibraryName) {
22573 @CMP_PARAMS = (@CMP_PARAMS, "-l-full", $TargetLibraryFName);
22574 }
22575 if($ShowRetVal) {
22576 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22577 }
22578 if($CrossGcc) {
22579 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22580 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022581 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22582 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022583 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022584 }
22585 if($ReportFormat and $ReportFormat ne "html")
22586 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022587 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22588 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022589 if($OutputReportPath) {
22590 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22591 }
22592 if($BinaryReportPath) {
22593 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22594 }
22595 if($SourceReportPath) {
22596 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22597 }
22598 if($LoggingPath) {
22599 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22600 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022601 if($CheckHeadersOnly) {
22602 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22603 }
22604 if($CheckObjectsOnly) {
22605 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
22606 }
22607 if($BinaryOnly) {
22608 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22609 }
22610 if($SourceOnly) {
22611 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22612 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022613 if($Browse) {
22614 @CMP_PARAMS = (@CMP_PARAMS, "-browse", $Browse);
22615 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022616 if($OpenReport) {
22617 @CMP_PARAMS = (@CMP_PARAMS, "-open");
22618 }
22619 if($Debug)
22620 {
22621 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22622 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022623 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022624 system("perl", $0, @CMP_PARAMS);
22625 exit($?>>8);
22626 }
22627 if(not $Descriptor{1}{"Dump"}
22628 or not $Descriptor{2}{"Dump"})
22629 { # need GCC toolchain to analyze
22630 # header files and libraries
22631 detect_default_paths("inc|lib|gcc");
22632 }
22633 if(not $Descriptor{1}{"Dump"})
22634 {
22635 if(not $CheckHeadersOnly) {
22636 readLibs(1);
22637 }
22638 if($CheckHeadersOnly) {
22639 setLanguage(1, "C++");
22640 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022641 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022642 searchForHeaders(1);
22643 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022644 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022645 }
22646 if(not $Descriptor{2}{"Dump"})
22647 {
22648 if(not $CheckHeadersOnly) {
22649 readLibs(2);
22650 }
22651 if($CheckHeadersOnly) {
22652 setLanguage(2, "C++");
22653 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022654 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022655 searchForHeaders(2);
22656 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022657 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022658 }
22659 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22660 { # support for old ABI dumps
22661 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022662 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022663 {
22664 $WORD_SIZE{1} = $WORD_SIZE{2};
22665 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22666 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022667 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022668 {
22669 $WORD_SIZE{2} = $WORD_SIZE{1};
22670 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22671 }
22672 }
22673 elsif(not $WORD_SIZE{1}
22674 and not $WORD_SIZE{2})
22675 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022676 $WORD_SIZE{1} = "4";
22677 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022678 }
22679 if($Descriptor{1}{"Dump"})
22680 { # support for old ABI dumps
22681 prepareTypes(1);
22682 }
22683 if($Descriptor{2}{"Dump"})
22684 { # support for old ABI dumps
22685 prepareTypes(2);
22686 }
22687 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22688 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22689 }
22690 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022691 if(not $CheckObjectsOnly)
22692 {
22693 if($Descriptor{1}{"Headers"}
22694 and not $Descriptor{1}{"Dump"}) {
22695 readHeaders(1);
22696 }
22697 if($Descriptor{2}{"Headers"}
22698 and not $Descriptor{2}{"Dump"}) {
22699 readHeaders(2);
22700 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022701 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022702
22703 # clean memory
22704 %SystemHeaders = ();
22705 %mangled_name_gcc = ();
22706
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022707 prepareSymbols(1);
22708 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022709
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022710 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022711 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022712
22713 # Virtual Tables
22714 registerVTable(1);
22715 registerVTable(2);
22716
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022717 if(not checkDump(1, "1.22")
22718 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022719 { # support for old ABI dumps
22720 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22721 {
22722 if($ClassName=~/</)
22723 { # templates
22724 if(not defined $VirtualTable{1}{$ClassName})
22725 { # synchronize
22726 delete($VirtualTable{2}{$ClassName});
22727 }
22728 }
22729 }
22730 }
22731
22732 registerOverriding(1);
22733 registerOverriding(2);
22734
22735 setVirtFuncPositions(1);
22736 setVirtFuncPositions(2);
22737
22738 # Other
22739 addParamNames(1);
22740 addParamNames(2);
22741
22742 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022743}
22744
22745sub compareAPIs($)
22746{
22747 my $Level = $_[0];
22748 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022749 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022750 if($Level eq "Binary") {
22751 printMsg("INFO", "comparing ABIs ...");
22752 }
22753 else {
22754 printMsg("INFO", "comparing APIs ...");
22755 }
22756 if($CheckHeadersOnly
22757 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022758 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022759 detectAdded_H($Level);
22760 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022761 }
22762 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022763 { # added/removed in libs
22764 detectAdded($Level);
22765 detectRemoved($Level);
22766 }
22767 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022768 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022769 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022770 if(keys(%{$CheckedSymbols{$Level}})) {
22771 mergeConstants($Level);
22772 }
22773 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022774
22775 $Cache{"mergeTypes"} = (); # free memory
22776
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022777 if($CheckHeadersOnly
22778 or $Level eq "Source")
22779 { # added/removed in headers
22780 mergeHeaders($Level);
22781 }
22782 else
22783 { # added/removed in libs
22784 mergeLibs($Level);
22785 if($CheckImpl
22786 and $Level eq "Binary") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022787 mergeImpl();
22788 }
22789 }
22790}
22791
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022792sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022793{
22794 my %Opts = (
22795 "OStarget"=>$OStarget,
22796 "Debug"=>$Debug,
22797 "Quiet"=>$Quiet,
22798 "LogMode"=>$LogMode,
22799 "CheckHeadersOnly"=>$CheckHeadersOnly,
22800
22801 "SystemRoot"=>$SystemRoot,
22802 "MODULES_DIR"=>$MODULES_DIR,
22803 "GCC_PATH"=>$GCC_PATH,
22804 "TargetSysInfo"=>$TargetSysInfo,
22805 "CrossPrefix"=>$CrossPrefix,
22806 "TargetLibraryName"=>$TargetLibraryName,
22807 "CrossGcc"=>$CrossGcc,
22808 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022809 "NoStdInc"=>$NoStdInc,
22810
22811 "BinaryOnly" => $BinaryOnly,
22812 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022813 );
22814 return \%Opts;
22815}
22816
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022817sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022818{
22819 my %CODE_ERROR = reverse(%ERROR_CODE);
22820 return $CODE_ERROR{$_[0]};
22821}
22822
22823sub scenario()
22824{
22825 if($StdOut)
22826 { # enable quiet mode
22827 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022828 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022829 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022830 if(not $LogMode)
22831 { # default
22832 $LogMode = "w";
22833 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022834 if($UserLang)
22835 { # --lang=C++
22836 $UserLang = uc($UserLang);
22837 $COMMON_LANGUAGE{1}=$UserLang;
22838 $COMMON_LANGUAGE{2}=$UserLang;
22839 }
22840 if($LoggingPath)
22841 {
22842 $OutputLogPath{1} = $LoggingPath;
22843 $OutputLogPath{2} = $LoggingPath;
22844 if($Quiet) {
22845 $COMMON_LOG_PATH = $LoggingPath;
22846 }
22847 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022848 if($Quick) {
22849 $ADD_TMPL_INSTANCES = 0;
22850 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022851 if($OutputDumpPath)
22852 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022853 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022854 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22855 }
22856 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022857 if($BinaryOnly and $SourceOnly)
22858 { # both --binary and --source
22859 # is the default mode
22860 $DoubleReport = 1;
22861 $JoinReport = 0;
22862 $BinaryOnly = 0;
22863 $SourceOnly = 0;
22864 if($OutputReportPath)
22865 { # --report-path
22866 $DoubleReport = 0;
22867 $JoinReport = 1;
22868 }
22869 }
22870 elsif($BinaryOnly or $SourceOnly)
22871 { # --binary or --source
22872 $DoubleReport = 0;
22873 $JoinReport = 0;
22874 }
22875 if($UseXML)
22876 { # --xml option
22877 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022878 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022879 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022880 if($ReportFormat)
22881 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022882 $ReportFormat = lc($ReportFormat);
22883 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022884 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022885 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022886 if($ReportFormat eq "htm")
22887 { # HTM == HTML
22888 $ReportFormat = "html";
22889 }
22890 elsif($ReportFormat eq "xml")
22891 { # --report-format=XML equal to --xml
22892 $UseXML = 1;
22893 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022894 }
22895 else
22896 { # default: HTML
22897 $ReportFormat = "html";
22898 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022899 if($DumpFormat)
22900 { # validate
22901 $DumpFormat = lc($DumpFormat);
22902 if($DumpFormat!~/\A(xml|perl)\Z/) {
22903 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22904 }
22905 if($DumpFormat eq "xml")
22906 { # --dump-format=XML equal to --xml
22907 $UseXML = 1;
22908 }
22909 }
22910 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022911 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022912 $DumpFormat = "perl";
22913 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022914 if($Quiet and $LogMode!~/a|n/)
22915 { # --quiet log
22916 if(-f $COMMON_LOG_PATH) {
22917 unlink($COMMON_LOG_PATH);
22918 }
22919 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022920 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022921 $CheckUndefined = 1;
22922 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022923 if($TestTool and $UseDumps)
22924 { # --test && --use-dumps == --test-dump
22925 $TestDump = 1;
22926 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022927 if($Tolerant)
22928 { # enable all
22929 $Tolerance = 1234;
22930 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022931 if($Help)
22932 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022933 HELP_MESSAGE();
22934 exit(0);
22935 }
22936 if($InfoMsg) {
22937 INFO_MESSAGE();
22938 exit(0);
22939 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022940 if($ShowVersion)
22941 {
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022942 printMsg("INFO", "ABI Compliance Checker (ABICC) $TOOL_VERSION\nCopyright (C) 2014 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.");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022943 exit(0);
22944 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022945 if($DumpVersion)
22946 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022947 printMsg("INFO", $TOOL_VERSION);
22948 exit(0);
22949 }
22950 if($ExtendedCheck) {
22951 $CheckHeadersOnly = 1;
22952 }
22953 if($SystemRoot_Opt)
22954 { # user defined root
22955 if(not -e $SystemRoot_Opt) {
22956 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22957 }
22958 $SystemRoot = $SystemRoot_Opt;
22959 $SystemRoot=~s/[\/]+\Z//g;
22960 if($SystemRoot) {
22961 $SystemRoot = get_abs_path($SystemRoot);
22962 }
22963 }
22964 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022965
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022966 if($SortDump)
22967 {
22968 $Data::Dumper::Useperl = 1;
22969 $Data::Dumper::Sortkeys = \&dump_sorting;
22970 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022971
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022972 if($TargetLibsPath)
22973 {
22974 if(not -f $TargetLibsPath) {
22975 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22976 }
22977 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22978 $TargetLibs{$Lib} = 1;
22979 }
22980 }
22981 if($TargetHeadersPath)
22982 { # --headers-list
22983 if(not -f $TargetHeadersPath) {
22984 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22985 }
22986 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22987 {
22988 $TargetHeaders{1}{$Header} = 1;
22989 $TargetHeaders{2}{$Header} = 1;
22990 }
22991 }
22992 if($TargetHeader)
22993 { # --header
22994 $TargetHeaders{1}{$TargetHeader} = 1;
22995 $TargetHeaders{2}{$TargetHeader} = 1;
22996 }
22997 if($TestTool
22998 or $TestDump)
22999 { # --test, --test-dump
23000 detect_default_paths("bin|gcc"); # to compile libs
23001 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023002 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
23003 $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023004 exit(0);
23005 }
23006 if($DumpSystem)
23007 { # --dump-system
23008 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023009 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023010 { # system XML descriptor
23011 if(not -f $DumpSystem) {
23012 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
23013 }
23014 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023015 foreach (@{$Ret->{"Tools"}})
23016 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023017 push_U($SystemPaths{"bin"}, $_);
23018 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023019 }
23020 if($Ret->{"CrossPrefix"}) {
23021 $CrossPrefix = $Ret->{"CrossPrefix"};
23022 }
23023 }
23024 elsif($SystemRoot_Opt)
23025 { # -sysroot "/" option
23026 # default target: /usr/lib, /usr/include
23027 # search libs: /usr/lib and /lib
23028 if(not -e $SystemRoot."/usr/lib") {
23029 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
23030 }
23031 if(not -e $SystemRoot."/lib") {
23032 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
23033 }
23034 if(not -e $SystemRoot."/usr/include") {
23035 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
23036 }
23037 readSystemDescriptor("
23038 <name>
23039 $DumpSystem
23040 </name>
23041 <headers>
23042 $SystemRoot/usr/include
23043 </headers>
23044 <libs>
23045 $SystemRoot/usr/lib
23046 </libs>
23047 <search_libs>
23048 $SystemRoot/lib
23049 </search_libs>");
23050 }
23051 else {
23052 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
23053 }
23054 detect_default_paths("bin|gcc"); # to check symbols
23055 if($OStarget eq "windows")
23056 { # to run dumpbin.exe
23057 # and undname.exe
23058 check_win32_env();
23059 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023060 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023061 exit(0);
23062 }
23063 if($CmpSystems)
23064 { # --cmp-systems
23065 detect_default_paths("bin"); # to extract dumps
23066 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023067 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023068 exit(0);
23069 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023070 if($GenerateTemplate)
23071 {
23072 writeFile("VERSION.xml", $DescriptorTemplate."\n");
23073 printMsg("INFO", "XML-descriptor template ./VERSION.xml has been generated");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023074 exit(0);
23075 }
23076 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023077 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023078 }
23079 else
23080 { # validate library name
23081 if($TargetLibraryName=~/[\*\/\\]/) {
23082 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
23083 }
23084 }
23085 if(not $TargetLibraryFName) {
23086 $TargetLibraryFName = $TargetLibraryName;
23087 }
23088 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
23089 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
23090 }
23091 if($SymbolsListPath)
23092 {
23093 if(not -f $SymbolsListPath) {
23094 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
23095 }
23096 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
23097 $SymbolsList{$Interface} = 1;
23098 }
23099 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023100 if($SkipSymbolsListPath)
23101 {
23102 if(not -f $SkipSymbolsListPath) {
23103 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
23104 }
23105 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
23106 $SkipSymbolsList{$Interface} = 1;
23107 }
23108 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023109 if($SkipHeadersPath)
23110 {
23111 if(not -f $SkipHeadersPath) {
23112 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
23113 }
23114 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023115 { # register for both versions
23116 $SkipHeadersList{1}{$Path} = 1;
23117 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023118 my ($CPath, $Type) = classifyPath($Path);
23119 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023120 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023121 }
23122 }
23123 if($ParamNamesPath)
23124 {
23125 if(not -f $ParamNamesPath) {
23126 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
23127 }
23128 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
23129 {
23130 if($Line=~s/\A(\w+)\;//)
23131 {
23132 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023133 if($Line=~/;(\d+);/)
23134 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023135 while($Line=~s/(\d+);(\w+)//) {
23136 $AddIntParams{$Interface}{$1}=$2;
23137 }
23138 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023139 else
23140 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023141 my $Num = 0;
23142 foreach my $Name (split(/;/, $Line)) {
23143 $AddIntParams{$Interface}{$Num++}=$Name;
23144 }
23145 }
23146 }
23147 }
23148 }
23149 if($AppPath)
23150 {
23151 if(not -f $AppPath) {
23152 exitStatus("Access_Error", "can't access file \'$AppPath\'");
23153 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040023154 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023155 $SymbolsList_App{$Interface} = 1;
23156 }
23157 }
23158 if($DumpAPI)
23159 { # --dump-abi
23160 # make an API dump
23161 create_ABI_Dump();
23162 exit($COMPILE_ERRORS);
23163 }
23164 # default: compare APIs
23165 # -d1 <path>
23166 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023167 compareInit();
23168 if($JoinReport or $DoubleReport)
23169 {
23170 compareAPIs("Binary");
23171 compareAPIs("Source");
23172 }
23173 elsif($BinaryOnly) {
23174 compareAPIs("Binary");
23175 }
23176 elsif($SourceOnly) {
23177 compareAPIs("Source");
23178 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023179 exitReport();
23180}
23181
23182scenario();