blob: f92660eb151b208b8ba5c3503d8de6f5448d4637 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04003# ABI Compliance Checker (ACC) 1.99.9
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 Ponomarenkod5958082014-01-23 13:36:03 +040020# - G++ (3.0-4.7, 4.8.3, recommended 4.5 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021# - GNU Binutils (readelf, c++filt, objdump)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022# - Perl 5 (5.8 or newer)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040024#
25# Mac OS X
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040026# - Xcode (g++, c++filt, otool, nm)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040027# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040028#
29# MS Windows
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040030# - MinGW (3.0-4.7, recommended 4.5 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040031# - MS Visual C++ (dumpbin, undname, cl)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040032# - Active Perl 5 (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040033# - Sigcheck v1.71 or newer
34# - Info-ZIP 3.0 (zip, unzip)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040035# - Ctags (5.8 or newer)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040036# - Add tool locations to the PATH environment variable
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040037# - Run vsvars32.bat (C:\Microsoft Visual Studio 9.0\Common7\Tools\)
38#
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040039# COMPATIBILITY
40# =============
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 Ponomarenkod5958082014-01-23 13:36:03 +040067my $TOOL_VERSION = "1.99.9";
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 Ponomarenkodde2dad2012-03-26 19:06:14 +0400152 "Dev1"=>"https://github.com/lvc/abi-compliance-checker",
153 "Dev2"=>"http://forge.ispras.ru/projects/abi-compliance-checker"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400154);
155
156my $ShortUsage = "ABI Compliance Checker (ACC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400157A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400158Copyright (C) 2014 ROSA Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400159License: GNU LGPL or GNU GPL
160
161Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400162Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400163
164OLD.xml and NEW.xml are XML-descriptors:
165
166 <version>
167 1.0
168 </version>
169
170 <headers>
171 /path/to/headers/
172 </headers>
173
174 <libs>
175 /path/to/libraries/
176 </libs>
177
178More info: $CmdName --help\n";
179
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400180if($#ARGV==-1)
181{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400182 printMsg("INFO", $ShortUsage);
183 exit(0);
184}
185
186foreach (2 .. $#ARGV)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400187{ # correct comma separated options
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400188 if($ARGV[$_-1] eq ",")
189 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400190 $ARGV[$_-2].=",".$ARGV[$_];
191 splice(@ARGV, $_-1, 2);
192 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400193 elsif($ARGV[$_-1]=~/,\Z/)
194 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400195 $ARGV[$_-1].=$ARGV[$_];
196 splice(@ARGV, $_, 1);
197 }
198 elsif($ARGV[$_]=~/\A,/
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400199 and $ARGV[$_] ne ",")
200 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400201 $ARGV[$_-1].=$ARGV[$_];
202 splice(@ARGV, $_, 1);
203 }
204}
205
206GetOptions("h|help!" => \$Help,
207 "i|info!" => \$InfoMsg,
208 "v|version!" => \$ShowVersion,
209 "dumpversion!" => \$DumpVersion,
210# general options
211 "l|lib|library=s" => \$TargetLibraryName,
212 "d1|old|o=s" => \$Descriptor{1}{"Path"},
213 "d2|new|n=s" => \$Descriptor{2}{"Path"},
214 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
215 "old-dumps!" => \$UseOldDumps,
216# extra options
217 "d|descriptor-template!" => \$GenerateTemplate,
218 "app|application=s" => \$AppPath,
219 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +0400220 "gcc-path|cross-gcc=s" => \$CrossGcc,
221 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
222 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400223 "sysroot=s" => \$SystemRoot_Opt,
224 "v1|version1|vnum=s" => \$TargetVersion{1},
225 "v2|version2=s" => \$TargetVersion{2},
226 "s|strict!" => \$StrictCompat,
227 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400228 "skip-symbols=s" => \$SkipSymbolsListPath,
229 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400230 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400231 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400232 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
233 "objects-only!" => \$CheckObjectsOnly_Opt,
234 "check-impl|check-implementation!" => \$CheckImpl,
235 "show-retval!" => \$ShowRetVal,
236 "use-dumps!" => \$UseDumps,
237 "nostdinc!" => \$NoStdInc,
238 "dump-system=s" => \$DumpSystem,
239 "sysinfo=s" => \$TargetSysInfo,
240 "cmp-systems!" => \$CmpSystems,
241 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400242 "ext|extended!" => \$ExtendedCheck,
243 "q|quiet!" => \$Quiet,
244 "stdout!" => \$StdOut,
245 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400246 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400247 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400248 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400249 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400250 "binary|bin|abi!" => \$BinaryOnly,
251 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400252 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400253# other options
254 "test!" => \$TestTool,
255 "test-dump!" => \$TestDump,
256 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400257 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400258 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400259 "p|params=s" => \$ParamNamesPath,
260 "relpath1|relpath=s" => \$RelativeDirectory{1},
261 "relpath2=s" => \$RelativeDirectory{2},
262 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400263 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400264 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400265 "bin-report-path=s" => \$BinaryReportPath,
266 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400267 "log-path=s" => \$LoggingPath,
268 "log1-path=s" => \$OutputLogPath{1},
269 "log2-path=s" => \$OutputLogPath{2},
270 "logging-mode=s" => \$LogMode,
271 "list-affected!" => \$ListAffected,
272 "l-full|lib-full=s" => \$TargetLibraryFName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400273 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400274 "b|browse=s" => \$Browse,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400275 "open!" => \$OpenReport,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400276 "extra-info=s" => \$ExtraInfo,
277 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400278 "force!" => \$Force,
279 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400280 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400281 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400282 "quick!" => \$Quick,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400283 "all-affected!" => \$AllAffected,
284 "skip-internal=s" => \$SkipInternal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400285) or ERR_MESSAGE();
286
287sub ERR_MESSAGE()
288{
289 printMsg("INFO", "\n".$ShortUsage);
290 exit($ERROR_CODE{"Error"});
291}
292
293my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
294my $SLIB_TYPE = $LIB_TYPE;
295if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
296{ # show as "shared" library
297 $SLIB_TYPE = "shared";
298}
299my $LIB_EXT = getLIB_EXT($OSgroup);
300my $AR_EXT = getAR_EXT($OSgroup);
301my $BYTE_SIZE = 8;
302my $COMMON_LOG_PATH = "logs/run.log";
303
304my $HelpMessage="
305NAME:
306 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400307 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400308
309DESCRIPTION:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400310 ABI Compliance Checker (ACC) is a tool for checking backward binary and
311 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
312 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
313 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
314 and/or source-level compatibility: changes in calling stack, v-table changes,
315 removed symbols, renamed fields, etc. Binary incompatibility may result in
316 crashing or incorrect behavior of applications built with an old version of
317 a library if they run on a new one. Source incompatibility may result in
318 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400319
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400320 The tool is intended for developers of software libraries and maintainers
321 of operating systems who are interested in ensuring backward compatibility,
322 i.e. allow old applications to run or to be recompiled with newer library
323 versions.
324
325 Also the tool can be used by ISVs for checking applications portability to
326 new library versions. Found issues can be taken into account when adapting
327 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400328
329 This tool is free software: you can redistribute it and/or modify it
330 under the terms of the GNU LGPL or GNU GPL.
331
332USAGE:
333 $CmdName [options]
334
335EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400336 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400337
338 OLD.xml and NEW.xml are XML-descriptors:
339
340 <version>
341 1.0
342 </version>
343
344 <headers>
345 /path1/to/header(s)/
346 /path2/to/header(s)/
347 ...
348 </headers>
349
350 <libs>
351 /path1/to/library(ies)/
352 /path2/to/library(ies)/
353 ...
354 </libs>
355
356INFORMATION OPTIONS:
357 -h|-help
358 Print this help.
359
360 -i|-info
361 Print complete info.
362
363 -v|-version
364 Print version information.
365
366 -dumpversion
367 Print the tool version ($TOOL_VERSION) and don't do anything else.
368
369GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400370 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400371 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400372
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400373 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400374 Descriptor of 1st (old) library version.
375 It may be one of the following:
376
377 1. XML-descriptor (VERSION.xml file):
378
379 <version>
380 1.0
381 </version>
382
383 <headers>
384 /path1/to/header(s)/
385 /path2/to/header(s)/
386 ...
387 </headers>
388
389 <libs>
390 /path1/to/library(ies)/
391 /path2/to/library(ies)/
392 ...
393 </libs>
394
395 ... (XML-descriptor template
396 can be generated by -d option)
397
398 2. ABI dump generated by -dump option
399 3. Directory with headers and/or $SLIB_TYPE libraries
400 4. Single header file
401 5. Single $SLIB_TYPE library
402 6. Comma separated list of headers and/or libraries
403
404 If you are using an 2-6 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400405 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400406
407 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400408 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400409
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400410 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400411 Descriptor of 2nd (new) library version.
412
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400413 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400414 Create library ABI dump for the input XML descriptor. You can
415 transfer it anywhere and pass instead of the descriptor. Also
416 it can be used for debugging the tool.
417
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400418 Supported ABI dump versions: 2.0<=V<=$ABI_DUMP_VERSION
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400419
420 -old-dumps
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400421 Enable support for old-version ABI dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0).\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400422
423sub HELP_MESSAGE() {
424 printMsg("INFO", $HelpMessage."
425MORE INFO:
426 $CmdName --info\n");
427}
428
429sub INFO_MESSAGE()
430{
431 printMsg("INFO", "$HelpMessage
432EXTRA OPTIONS:
433 -d|-descriptor-template
434 Create XML-descriptor template ./VERSION.xml
435
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400436 -app|-application PATH
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200437 This option allows one to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400438 for portability to the new library version.
439
440 -static-libs
441 Check static libraries instead of the shared ones. The <libs> section
442 of the XML-descriptor should point to static libraries location.
443
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400444 -cross-gcc|-gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400445 Path to the cross GCC compiler to use instead of the usual (host) GCC.
446
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400447 -cross-prefix|-gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400448 GCC toolchain prefix.
449
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400450 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400451 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400452 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400453
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400454 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400455 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200456 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400457
458 In general case you should specify it in the XML-descriptor:
459 <version>
460 VERSION
461 </version>
462
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400463 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400464 Specify 2nd library version outside the descriptor.
465
466 -s|-strict
467 Treat all compatibility warnings as problems. Add a number of \"Low\"
468 severity problems to the return value of the tool.
469
470 -headers-only
471 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
472 provide a low quality compatibility report with false positives and
473 without detecting of added/removed symbols.
474
475 Alternatively you can write \"none\" word to the <libs> section
476 in the XML-descriptor:
477 <libs>
478 none
479 </libs>
480
481 -objects-only
482 Check $SLIB_TYPE libraries without header files. It is easy to run, but may
483 provide a low quality compatibility report with false positives and
484 without analysis of changes in parameters and data types.
485
486 Alternatively you can write \"none\" word to the <headers> section
487 in the XML-descriptor:
488 <headers>
489 none
490 </headers>
491
492 -check-impl|-check-implementation
493 Compare canonified disassembled binary code of $SLIB_TYPE libraries to
494 detect changes in the implementation. Add \'Problems with Implementation\'
495 section to the report.
496
497 -show-retval
498 Show the symbol's return type in the report.
499
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400500 -symbols-list PATH
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200501 This option allows one to specify a file with a list of symbols (mangled
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400502 names in C++) that should be checked, other symbols will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400503
504 -skip-symbols PATH
505 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400506
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400507 -headers-list PATH
508 The file with a list of headers, that should be checked/dumped.
509
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400510 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400511 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400512
513 -header NAME
514 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400515
516 -use-dumps
517 Make dumps for two versions of a library and compare dumps. This should
518 increase the performance of the tool and decrease the system memory usage.
519
520 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400521 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400522
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400523 -dump-system NAME -sysroot DIR
524 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400525 create XML descriptors and make ABI dumps for each library. The result
526 set of ABI dumps can be compared (--cmp-systems) with the other one
527 created for other version of operating system in order to check them for
528 compatibility. Do not forget to specify -cross-gcc option if your target
529 system requires some specific version of GCC compiler (different from
530 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400531 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400532
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400533 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400534 The same as the previous option but takes an XML descriptor of the target
535 system as input, where you should describe it:
536
537 /* Primary sections */
538
539 <name>
540 /* Name of the system */
541 </name>
542
543 <headers>
544 /* The list of paths to header files and/or
545 directories with header files, one per line */
546 </headers>
547
548 <libs>
549 /* The list of paths to shared libraries and/or
550 directories with shared libraries, one per line */
551 </libs>
552
553 /* Optional sections */
554
555 <search_headers>
556 /* List of directories to be searched
557 for header files to automatically
558 generate include paths, one per line */
559 </search_headers>
560
561 <search_libs>
562 /* List of directories to be searched
563 for shared libraries to resolve
564 dependencies, one per line */
565 </search_libs>
566
567 <tools>
568 /* List of directories with tools used
569 for analysis (GCC toolchain), one per line */
570 </tools>
571
572 <cross_prefix>
573 /* GCC toolchain prefix.
574 Examples:
575 arm-linux-gnueabi
576 arm-none-symbianelf */
577 </cross_prefix>
578
579 <gcc_options>
580 /* Additional GCC options, one per line */
581 </gcc_options>
582
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400583 -sysinfo DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400584 This option may be used with -dump-system to dump ABI of operating
585 systems and configure the dumping process.
586 Default:
587 modules/Targets/{unix, symbian, windows}
588
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400589 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400590 Compare two system ABI dumps. Create compatibility reports for each
591 library and the common HTML report including the summary of test
592 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400593 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400594
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400595 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400596 The file with a list of libraries, that should be dumped by
597 the -dump-system option or should be checked by the -cmp-systems option.
598
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400599 -ext|-extended
600 If your library A is supposed to be used by other library B and you
601 want to control the ABI of B, then you should enable this option. The
602 tool will check for changes in all data types, even if they are not
603 used by any function in the library A. Such data types are not part
604 of the A library ABI, but may be a part of the ABI of the B library.
605
606 The short scheme is:
607 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
608
609 -q|-quiet
610 Print all messages to the file instead of stdout and stderr.
611 Default path (can be changed by -log-path option):
612 $COMMON_LOG_PATH
613
614 -stdout
615 Print analysis results (compatibility reports and ABI dumps) to stdout
616 instead of creating a file. This would allow piping data to other programs.
617
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400618 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400619 Change format of compatibility report.
620 Formats:
621 htm - HTML format (default)
622 xml - XML format
623
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400624 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400625 Change format of ABI dump.
626 Formats:
627 perl - Data::Dumper format (default)
628 xml - XML format
629
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400630 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400631 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400632
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400633 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400634 Set library language (C or C++). You can use this option if the tool
635 cannot auto-detect a language. This option may be useful for checking
636 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400637
638 -arch ARCH
639 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
640 ect.). The option is useful if the tool cannot detect correct architecture
641 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400642
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400643 -binary|-bin|-abi
644 Show \"Binary\" compatibility problems only.
645 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400646 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400647
648 -source|-src|-api
649 Show \"Source\" compatibility problems only.
650 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400651 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400652
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400653 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400654 The maximum number of affected symbols listed under the description
655 of the changed type in the report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400656
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400657OTHER OPTIONS:
658 -test
659 Run internal tests. Create two binary incompatible versions of a sample
660 library and run the tool to check them for compatibility. This option
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200661 allows one to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400662
663 -test-dump
664 Test ability to create, read and compare ABI dumps.
665
666 -debug
667 Debugging mode. Print debug info on the screen. Save intermediate
668 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400669 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400670
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400671 Also consider using --dump option for debugging the tool.
672
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400673 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400674 If your header files are written in C language and can be compiled
675 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
676 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400677
678 -cpp-incompatible
679 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400680
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400681 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400682 Path to file with the function parameter names. It can be used
683 for improving report view if the library header files have no
684 parameter names. File format:
685
686 func1;param1;param2;param3 ...
687 func2;param1;param2;param3 ...
688 ...
689
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 -relpath PATH
691 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400692 for dumping the library ABI (see -dump option).
693
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400694 -relpath1 PATH
695 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400696
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400697 -relpath2 PATH
698 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400699
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400700 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400701 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400702 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400703 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400704
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400705 -sort
706 Enable sorting of data in ABI dumps.
707
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400708 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400709 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400710 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400711 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400712
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400713 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400714 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400715 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400716 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400717
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400718 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400719 Path to \"Source\" compatibility report.
720 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400721 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400722
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400723 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400724 Log path for all messages.
725 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400726 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400727
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400728 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400729 Log path for 1st version of a library.
730 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400731 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400732
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400733 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400734 Log path for 2nd version of a library.
735 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400736 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400737
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400738 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400739 Change logging mode.
740 Modes:
741 w - overwrite old logs (default)
742 a - append old logs
743 n - do not write any logs
744
745 -list-affected
746 Generate file with the list of incompatible
747 symbols beside the HTML compatibility report.
748 Use 'c++filt \@file' command from GNU binutils
749 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400750 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400751 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400752 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400753
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400754 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400755 The component name in the title and summary of the HTML report.
756 Default:
757 library
758
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400759 -l-full|-lib-full NAME
760 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400761 will be displayed a name specified by -l option.
762
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400763 -b|-browse PROGRAM
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400764 Open report(s) in the browser (firefox, opera, etc.).
765
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400766 -open
767 Open report(s) in the default browser.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400768
769 -extra-info DIR
770 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400771
772 -extra-dump
773 Create extended ABI dump containing all symbols
774 from the translation unit.
775
776 -force
777 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400778
779 -tolerance LEVEL
780 Apply a set of heuristics to successfully compile input
781 header files. You can enable several tolerance levels by
782 joining them into one string (e.g. 13, 124, etc.).
783 Levels:
784 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
785 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
786 3 - skip headers that iclude non-Linux headers
787 4 - skip headers included by others
788
789 -tolerant
790 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400791
792 -check
793 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400794
795 -quick
796 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400797
798 -skip-internal PATTERN
799 Do not check internal interfaces matched by the pattern.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400800
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400801REPORT:
802 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400803 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400804
805 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400806 logs/LIB_NAME/V1/log.txt
807 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400808
809EXIT CODES:
810 0 - Compatible. The tool has run without any errors.
811 non-zero - Incompatible or the tool has run with errors.
812
813REPORT BUGS TO:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400814 Andrey Ponomarenko <aponomarenko\@rosalab.ru>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400815
816MORE INFORMATION:
817 ".$HomePage{"Wiki"}."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400818 ".$HomePage{"Dev1"}."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400819}
820
821my $DescriptorTemplate = "
822<?xml version=\"1.0\" encoding=\"utf-8\"?>
823<descriptor>
824
825/* Primary sections */
826
827<version>
828 /* Version of the library */
829</version>
830
831<headers>
832 /* The list of paths to header files and/or
833 directories with header files, one per line */
834</headers>
835
836<libs>
837 /* The list of paths to shared libraries (*.$LIB_EXT) and/or
838 directories with shared libraries, one per line */
839</libs>
840
841/* Optional sections */
842
843<include_paths>
844 /* The list of include paths that will be provided
845 to GCC to compile library headers, one per line.
846 NOTE: If you define this section then the tool
847 will not automatically generate include paths */
848</include_paths>
849
850<add_include_paths>
851 /* The list of include paths that will be added
852 to the automatically generated include paths, one per line */
853</add_include_paths>
854
855<skip_include_paths>
856 /* The list of include paths that will be removed from the
857 list of automatically generated include paths, one per line */
858</skip_include_paths>
859
860<gcc_options>
861 /* Additional GCC options, one per line */
862</gcc_options>
863
864<include_preamble>
865 /* The list of header files that will be
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +0400866 included before other headers, one per line */
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400867</include_preamble>
868
869<defines>
870 /* The list of defines that will be added at the
871 headers compiling stage, one per line:
872 #define A B
873 #define C D */
874</defines>
875
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +0400876<add_namespaces>
877 /* The list of namespaces that should be added to the alanysis
878 if the tool cannot find them automatically, one per line */
879</add_namespaces>
880
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400881<skip_types>
882 /* The list of data types, that
883 should not be checked, one per line */
884</skip_types>
885
886<skip_symbols>
887 /* The list of functions (mangled/symbol names in C++),
888 that should not be checked, one per line */
889</skip_symbols>
890
891<skip_namespaces>
892 /* The list of C++ namespaces, that
893 should not be checked, one per line */
894</skip_namespaces>
895
896<skip_constants>
897 /* The list of constants that should
898 not be checked, one name per line */
899</skip_constants>
900
901<skip_headers>
902 /* The list of header files and/or directories
903 with header files that should not be checked, one per line */
904</skip_headers>
905
906<skip_libs>
907 /* The list of shared libraries and/or directories
908 with shared libraries that should not be checked, one per line */
909</skip_libs>
910
911<skip_including>
912 /* The list of header files, that cannot be included
913 directly (or non-self compiled ones), one per line */
914</skip_including>
915
916<search_headers>
917 /* List of directories to be searched
918 for header files to automatically
919 generate include paths, one per line. */
920</search_headers>
921
922<search_libs>
923 /* List of directories to be searched
924 for shared librariess to resolve
925 dependencies, one per line */
926</search_libs>
927
928<tools>
929 /* List of directories with tools used
930 for analysis (GCC toolchain), one per line */
931</tools>
932
933<cross_prefix>
934 /* GCC toolchain prefix.
935 Examples:
936 arm-linux-gnueabi
937 arm-none-symbianelf */
938</cross_prefix>
939
940</descriptor>";
941
942my %Operator_Indication = (
943 "not" => "~",
944 "assign" => "=",
945 "andassign" => "&=",
946 "orassign" => "|=",
947 "xorassign" => "^=",
948 "or" => "|",
949 "xor" => "^",
950 "addr" => "&",
951 "and" => "&",
952 "lnot" => "!",
953 "eq" => "==",
954 "ne" => "!=",
955 "lt" => "<",
956 "lshift" => "<<",
957 "lshiftassign" => "<<=",
958 "rshiftassign" => ">>=",
959 "call" => "()",
960 "mod" => "%",
961 "modassign" => "%=",
962 "subs" => "[]",
963 "land" => "&&",
964 "lor" => "||",
965 "rshift" => ">>",
966 "ref" => "->",
967 "le" => "<=",
968 "deref" => "*",
969 "mult" => "*",
970 "preinc" => "++",
971 "delete" => " delete",
972 "vecnew" => " new[]",
973 "vecdelete" => " delete[]",
974 "predec" => "--",
975 "postinc" => "++",
976 "postdec" => "--",
977 "plusassign" => "+=",
978 "plus" => "+",
979 "minus" => "-",
980 "minusassign" => "-=",
981 "gt" => ">",
982 "ge" => ">=",
983 "new" => " new",
984 "multassign" => "*=",
985 "divassign" => "/=",
986 "div" => "/",
987 "neg" => "-",
988 "pos" => "+",
989 "memref" => "->*",
990 "compound" => "," );
991
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400992my %UnknownOperator;
993
994my %NodeType= (
995 "array_type" => "Array",
996 "binfo" => "Other",
997 "boolean_type" => "Intrinsic",
998 "complex_type" => "Intrinsic",
999 "const_decl" => "Other",
1000 "enumeral_type" => "Enum",
1001 "field_decl" => "Other",
1002 "function_decl" => "Other",
1003 "function_type" => "FunctionType",
1004 "identifier_node" => "Other",
1005 "integer_cst" => "Other",
1006 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001007 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001008 "method_type" => "MethodType",
1009 "namespace_decl" => "Other",
1010 "parm_decl" => "Other",
1011 "pointer_type" => "Pointer",
1012 "real_cst" => "Other",
1013 "real_type" => "Intrinsic",
1014 "record_type" => "Struct",
1015 "reference_type" => "Ref",
1016 "string_cst" => "Other",
1017 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001018 "template_type_parm" => "TemplateParam",
1019 "typename_type" => "TypeName",
1020 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001021 "tree_list" => "Other",
1022 "tree_vec" => "Other",
1023 "type_decl" => "Other",
1024 "union_type" => "Union",
1025 "var_decl" => "Other",
1026 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001027 "nop_expr" => "Other", #
1028 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001029 "offset_type" => "Other" );
1030
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001031my %CppKeywords_C = map {$_=>1} (
1032 # C++ 2003 keywords
1033 "public",
1034 "protected",
1035 "private",
1036 "default",
1037 "template",
1038 "new",
1039 #"asm",
1040 "dynamic_cast",
1041 "auto",
1042 "try",
1043 "namespace",
1044 "typename",
1045 "using",
1046 "reinterpret_cast",
1047 "friend",
1048 "class",
1049 "virtual",
1050 "const_cast",
1051 "mutable",
1052 "static_cast",
1053 "export",
1054 # C++0x keywords
1055 "noexcept",
1056 "nullptr",
1057 "constexpr",
1058 "static_assert",
1059 "explicit",
1060 # cannot be used as a macro name
1061 # as it is an operator in C++
1062 "and",
1063 #"and_eq",
1064 "not",
1065 #"not_eq",
1066 "or"
1067 #"or_eq",
1068 #"bitand",
1069 #"bitor",
1070 #"xor",
1071 #"xor_eq",
1072 #"compl"
1073);
1074
1075my %CppKeywords_F = map {$_=>1} (
1076 "delete",
1077 "catch",
1078 "alignof",
1079 "thread_local",
1080 "decltype",
1081 "typeid"
1082);
1083
1084my %CppKeywords_O = map {$_=>1} (
1085 "bool",
1086 "register",
1087 "inline",
1088 "operator"
1089);
1090
1091my %CppKeywords_A = map {$_=>1} (
1092 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001093 "throw",
1094 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001095);
1096
1097foreach (keys(%CppKeywords_C),
1098keys(%CppKeywords_F),
1099keys(%CppKeywords_O)) {
1100 $CppKeywords_A{$_}=1;
1101}
1102
1103# Header file extensions as described by gcc
1104my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
1105
1106my %IntrinsicMangling = (
1107 "void" => "v",
1108 "bool" => "b",
1109 "wchar_t" => "w",
1110 "char" => "c",
1111 "signed char" => "a",
1112 "unsigned char" => "h",
1113 "short" => "s",
1114 "unsigned short" => "t",
1115 "int" => "i",
1116 "unsigned int" => "j",
1117 "long" => "l",
1118 "unsigned long" => "m",
1119 "long long" => "x",
1120 "__int64" => "x",
1121 "unsigned long long" => "y",
1122 "__int128" => "n",
1123 "unsigned __int128" => "o",
1124 "float" => "f",
1125 "double" => "d",
1126 "long double" => "e",
1127 "__float80" => "e",
1128 "__float128" => "g",
1129 "..." => "z"
1130);
1131
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001132my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
1133
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001134my %StdcxxMangling = (
1135 "3std"=>"St",
1136 "3std9allocator"=>"Sa",
1137 "3std12basic_string"=>"Sb",
1138 "3std12basic_stringIcE"=>"Ss",
1139 "3std13basic_istreamIcE"=>"Si",
1140 "3std13basic_ostreamIcE"=>"So",
1141 "3std14basic_iostreamIcE"=>"Sd"
1142);
1143
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001144my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001145my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1146
1147my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001148my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001149
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001150my %ConstantSuffix = (
1151 "unsigned int"=>"u",
1152 "long"=>"l",
1153 "unsigned long"=>"ul",
1154 "long long"=>"ll",
1155 "unsigned long long"=>"ull"
1156);
1157
1158my %ConstantSuffixR =
1159reverse(%ConstantSuffix);
1160
1161my %OperatorMangling = (
1162 "~" => "co",
1163 "=" => "aS",
1164 "|" => "or",
1165 "^" => "eo",
1166 "&" => "an",#ad (addr)
1167 "==" => "eq",
1168 "!" => "nt",
1169 "!=" => "ne",
1170 "<" => "lt",
1171 "<=" => "le",
1172 "<<" => "ls",
1173 "<<=" => "lS",
1174 ">" => "gt",
1175 ">=" => "ge",
1176 ">>" => "rs",
1177 ">>=" => "rS",
1178 "()" => "cl",
1179 "%" => "rm",
1180 "[]" => "ix",
1181 "&&" => "aa",
1182 "||" => "oo",
1183 "*" => "ml",#de (deref)
1184 "++" => "pp",#
1185 "--" => "mm",#
1186 "new" => "nw",
1187 "delete" => "dl",
1188 "new[]" => "na",
1189 "delete[]" => "da",
1190 "+=" => "pL",
1191 "+" => "pl",#ps (pos)
1192 "-" => "mi",#ng (neg)
1193 "-=" => "mI",
1194 "*=" => "mL",
1195 "/=" => "dV",
1196 "&=" => "aN",
1197 "|=" => "oR",
1198 "%=" => "rM",
1199 "^=" => "eO",
1200 "/" => "dv",
1201 "->*" => "pm",
1202 "->" => "pt",#rf (ref)
1203 "," => "cm",
1204 "?" => "qu",
1205 "." => "dt",
1206 "sizeof"=> "sz"#st
1207);
1208
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001209my %Intrinsic_Keywords = map {$_=>1} (
1210 "true",
1211 "false",
1212 "_Bool",
1213 "_Complex",
1214 "const",
1215 "int",
1216 "long",
1217 "void",
1218 "short",
1219 "float",
1220 "volatile",
1221 "restrict",
1222 "unsigned",
1223 "signed",
1224 "char",
1225 "double",
1226 "class",
1227 "struct",
1228 "union",
1229 "enum"
1230);
1231
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001232my %GlibcHeader = map {$_=>1} (
1233 "aliases.h",
1234 "argp.h",
1235 "argz.h",
1236 "assert.h",
1237 "cpio.h",
1238 "ctype.h",
1239 "dirent.h",
1240 "envz.h",
1241 "errno.h",
1242 "error.h",
1243 "execinfo.h",
1244 "fcntl.h",
1245 "fstab.h",
1246 "ftw.h",
1247 "glob.h",
1248 "grp.h",
1249 "iconv.h",
1250 "ifaddrs.h",
1251 "inttypes.h",
1252 "langinfo.h",
1253 "limits.h",
1254 "link.h",
1255 "locale.h",
1256 "malloc.h",
1257 "math.h",
1258 "mntent.h",
1259 "monetary.h",
1260 "nl_types.h",
1261 "obstack.h",
1262 "printf.h",
1263 "pwd.h",
1264 "regex.h",
1265 "sched.h",
1266 "search.h",
1267 "setjmp.h",
1268 "shadow.h",
1269 "signal.h",
1270 "spawn.h",
1271 "stdarg.h",
1272 "stdint.h",
1273 "stdio.h",
1274 "stdlib.h",
1275 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001276 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001277 "tar.h",
1278 "termios.h",
1279 "time.h",
1280 "ulimit.h",
1281 "unistd.h",
1282 "utime.h",
1283 "wchar.h",
1284 "wctype.h",
1285 "wordexp.h" );
1286
1287my %GlibcDir = map {$_=>1} (
1288 "arpa",
1289 "bits",
1290 "gnu",
1291 "netinet",
1292 "net",
1293 "nfs",
1294 "rpc",
1295 "sys",
1296 "linux" );
1297
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001298my %WinHeaders = map {$_=>1} (
1299 "dos.h",
1300 "process.h",
1301 "winsock.h",
1302 "config-win.h",
1303 "mem.h",
1304 "windows.h",
1305 "winsock2.h",
1306 "crtdbg.h",
1307 "ws2tcpip.h"
1308);
1309
1310my %ObsoleteHeaders = map {$_=>1} (
1311 "iostream.h",
1312 "fstream.h"
1313);
1314
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001315my %AlienHeaders = map {$_=>1} (
1316 # Solaris
1317 "thread.h",
1318 "sys/atomic.h",
1319 # HPUX
1320 "sys/stream.h",
1321 # Symbian
1322 "AknDoc.h",
1323 # Atari ST
1324 "ext.h",
1325 "tos.h",
1326 # MS-DOS
1327 "alloc.h",
1328 # Sparc
1329 "sys/atomic.h"
1330);
1331
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001332my %ConfHeaders = map {$_=>1} (
1333 "atomic",
1334 "conf.h",
1335 "config.h",
1336 "configure.h",
1337 "build.h",
1338 "setup.h"
1339);
1340
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001341my %LocalIncludes = map {$_=>1} (
1342 "/usr/local/include",
1343 "/usr/local" );
1344
1345my %OS_AddPath=(
1346# These paths are needed if the tool cannot detect them automatically
1347 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001348 "include"=>[
1349 "/Library",
1350 "/Developer/usr/include"
1351 ],
1352 "lib"=>[
1353 "/Library",
1354 "/Developer/usr/lib"
1355 ],
1356 "bin"=>[
1357 "/Developer/usr/bin"
1358 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001359 },
1360 "beos"=>{
1361 # Haiku has GCC 2.95.3 by default
1362 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001363 "include"=>[
1364 "/boot/common",
1365 "/boot/develop"
1366 ],
1367 "lib"=>[
1368 "/boot/common/lib",
1369 "/boot/system/lib",
1370 "/boot/apps"
1371 ],
1372 "bin"=>[
1373 "/boot/common/bin",
1374 "/boot/system/bin",
1375 "/boot/develop/abi"
1376 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001377 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001378);
1379
1380my %Slash_Type=(
1381 "default"=>"/",
1382 "windows"=>"\\"
1383);
1384
1385my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1386
1387# Global Variables
1388my %COMMON_LANGUAGE=(
1389 1 => "C",
1390 2 => "C" );
1391
1392my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001393my $MAX_CPPFILT_FILE_SIZE = 50000;
1394my $CPPFILT_SUPPORT_FILE;
1395
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001396my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1397
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001398my $STDCXX_TESTING = 0;
1399my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001400my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001401
1402my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
1403my $CheckObjectsOnly = $CheckObjectsOnly_Opt;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001404
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001405my $TargetComponent;
1406
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001407my $CheckUndefined = 0;
1408
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001409# Set Target Component Name
1410if($TargetComponent_Opt) {
1411 $TargetComponent = lc($TargetComponent_Opt);
1412}
1413else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001414{ # default: library
1415 # other components: header, system, ...
1416 $TargetComponent = "library";
1417}
1418
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001419my $TOP_REF = "<a style='font-size:11px;' href='#Top'>to the top</a>";
1420
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001421my $SystemRoot;
1422
1423my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001424my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001425my %LOG_PATH;
1426my %DEBUG_PATH;
1427my %Cache;
1428my %LibInfo;
1429my $COMPILE_ERRORS = 0;
1430my %CompilerOptions;
1431my %CheckedDyLib;
1432my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1433
1434# Constants (#defines)
1435my %Constants;
1436my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001437my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001438
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001439# Extra Info
1440my %SymbolHeader;
1441my %KnownLibs;
1442
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001443# Templates
1444my %TemplateInstance;
1445my %BasicTemplate;
1446my %TemplateArg;
1447my %TemplateDecl;
1448my %TemplateMap;
1449
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001450# Types
1451my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001452my %SkipTypes = (
1453 "1"=>{},
1454 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001455my %CheckedTypes;
1456my %TName_Tid;
1457my %EnumMembName_Id;
1458my %NestedNameSpaces = (
1459 "1"=>{},
1460 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001461my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001462my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001463my %ClassVTable;
1464my %ClassVTable_Content;
1465my %VTableClass;
1466my %AllocableClass;
1467my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001468my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001469my %Class_SubClasses;
1470my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001471my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001472my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001473
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001474my %CheckedTypeInfo;
1475
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001476# Typedefs
1477my %Typedef_BaseName;
1478my %Typedef_Tr;
1479my %Typedef_Eq;
1480my %StdCxxTypedef;
1481my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001482my %MissedBase;
1483my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001484my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001485
1486# Symbols
1487my %SymbolInfo;
1488my %tr_name;
1489my %mangled_name_gcc;
1490my %mangled_name;
1491my %SkipSymbols = (
1492 "1"=>{},
1493 "2"=>{} );
1494my %SkipNameSpaces = (
1495 "1"=>{},
1496 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001497my %AddNameSpaces = (
1498 "1"=>{},
1499 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001500my %SymbolsList;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001501my %SkipSymbolsList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001502my %SymbolsList_App;
1503my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001504my %Symbol_Library = (
1505 "1"=>{},
1506 "2"=>{} );
1507my %Library_Symbol = (
1508 "1"=>{},
1509 "2"=>{} );
1510my %DepSymbol_Library = (
1511 "1"=>{},
1512 "2"=>{} );
1513my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001514 "1"=>{},
1515 "2"=>{} );
1516my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001517my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001518my %AddIntParams;
1519my %Interface_Impl;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001520my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001521my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001522my %Library_Needed= (
1523 "1"=>{},
1524 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001525
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001526# Extra Info
1527my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001528my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001529
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001530# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001531my %Include_Preamble = (
1532 "1"=>[],
1533 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001534my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001535my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001536my %HeaderName_Paths;
1537my %Header_Dependency;
1538my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001539my %Include_Paths = (
1540 "1"=>[],
1541 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001542my %INC_PATH_AUTODETECT = (
1543 "1"=>1,
1544 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001545my %Add_Include_Paths = (
1546 "1"=>[],
1547 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001548my %Skip_Include_Paths;
1549my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001550my %Header_ErrorRedirect;
1551my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001552my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001553my %Header_ShouldNotBeUsed;
1554my %RecursiveIncludes;
1555my %Header_Include_Prefix;
1556my %SkipHeaders;
1557my %SkipHeadersList=(
1558 "1"=>{},
1559 "2"=>{} );
1560my %SkipLibs;
1561my %Include_Order;
1562my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001563my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001564my %TUnit_Funcs;
1565my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001566
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001567my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001568 "1"=>0,
1569 "2"=>0 );
1570my %AutoPreambleMode = (
1571 "1"=>0,
1572 "2"=>0 );
1573my %MinGWMode = (
1574 "1"=>0,
1575 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001576my %Cpp0xMode = (
1577 "1"=>0,
1578 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001579
1580# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001581my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001582my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001583my %RegisteredSONAMEs;
1584my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001585
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001586my %CheckedArch;
1587
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001588# System Objects
1589my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001590my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001591my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001592
1593# System Headers
1594my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001595my @DefaultCppPaths;
1596my @DefaultGccPaths;
1597my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001598my %DefaultCppHeader;
1599my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001600my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001601
1602# Merging
1603my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001604my $Version;
1605my %AddedInt;
1606my %RemovedInt;
1607my %AddedInt_Virt;
1608my %RemovedInt_Virt;
1609my %VirtualReplacement;
1610my %ChangedTypedef;
1611my %CompatRules;
1612my %IncompleteRules;
1613my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001614my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001615my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001616my %ReturnedClass;
1617my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001618my %SourceAlternative;
1619my %SourceAlternative_B;
1620my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001621my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001622
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001623# Calling Conventions
1624my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001625 1=>{ "R"=>0, "P"=>0 },
1626 2=>{ "R"=>0, "P"=>0 }
1627);
1628
1629# ABI Dump
1630my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001631
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001632# OS Compliance
1633my %TargetLibs;
1634my %TargetHeaders;
1635
1636# OS Specifics
1637my $OStarget = $OSgroup;
1638my %TargetTools;
1639
1640# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001641my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001642
1643# Recursion locks
1644my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001645my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001646my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001647my @RecurInclude;
1648my @RecurConstant;
1649
1650# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001651my %SystemPaths = (
1652 "include"=>[],
1653 "lib"=>[],
1654 "bin"=>[]
1655);
1656my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001657my $GCC_PATH;
1658
1659# Symbols versioning
1660my %SymVer = (
1661 "1"=>{},
1662 "2"=>{} );
1663
1664# Problem descriptions
1665my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001666my %CompatProblems_Constants;
1667my %CompatProblems_Impl;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001668my %TotalAffected;
1669
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001670# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001671my $ContentID = 1;
1672my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1673my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1674my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1675my $ContentSpanEnd = "</span>\n";
1676my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1677my $ContentDivEnd = "</div>\n";
1678my $Content_Counter = 0;
1679
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001680# Modes
1681my $JoinReport = 1;
1682my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001683
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001684my %Severity_Val=(
1685 "High"=>3,
1686 "Medium"=>2,
1687 "Low"=>1,
1688 "Safe"=>-1
1689);
1690
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001691sub get_Modules()
1692{
1693 my $TOOL_DIR = get_dirname($0);
1694 if(not $TOOL_DIR)
1695 { # patch for MS Windows
1696 $TOOL_DIR = ".";
1697 }
1698 my @SEARCH_DIRS = (
1699 # tool's directory
1700 abs_path($TOOL_DIR),
1701 # relative path to modules
1702 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001703 # install path
1704 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001705 );
1706 foreach my $DIR (@SEARCH_DIRS)
1707 {
1708 if(not is_abs($DIR))
1709 { # relative path
1710 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1711 }
1712 if(-d $DIR."/modules") {
1713 return $DIR."/modules";
1714 }
1715 }
1716 exitStatus("Module_Error", "can't find modules");
1717}
1718
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001719my %LoadedModules = ();
1720
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001721sub loadModule($)
1722{
1723 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001724 if(defined $LoadedModules{$Name}) {
1725 return;
1726 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001727 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1728 if(not -f $Path) {
1729 exitStatus("Module_Error", "can't access \'$Path\'");
1730 }
1731 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001732 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001733}
1734
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001735sub readModule($$)
1736{
1737 my ($Module, $Name) = @_;
1738 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1739 if(not -f $Path) {
1740 exitStatus("Module_Error", "can't access \'$Path\'");
1741 }
1742 return readFile($Path);
1743}
1744
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001745sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001746{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001747 my $Number = $_[0];
1748 if(not $Number) {
1749 $Number = 1;
1750 }
1751 else {
1752 $Number = int($Number)+1;
1753 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001754 if($Number>3) {
1755 return $Number."th";
1756 }
1757 elsif($Number==1) {
1758 return "1st";
1759 }
1760 elsif($Number==2) {
1761 return "2nd";
1762 }
1763 elsif($Number==3) {
1764 return "3rd";
1765 }
1766 else {
1767 return $Number;
1768 }
1769}
1770
1771sub search_Tools($)
1772{
1773 my $Name = $_[0];
1774 return "" if(not $Name);
1775 if(my @Paths = keys(%TargetTools))
1776 {
1777 foreach my $Path (@Paths)
1778 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001779 if(-f join_P($Path, $Name)) {
1780 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001781 }
1782 if($CrossPrefix)
1783 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001784 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001785 if(-f $Candidate) {
1786 return $Candidate;
1787 }
1788 }
1789 }
1790 }
1791 else {
1792 return "";
1793 }
1794}
1795
1796sub synch_Cmd($)
1797{
1798 my $Name = $_[0];
1799 if(not $GCC_PATH)
1800 { # GCC was not found yet
1801 return "";
1802 }
1803 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001804 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001805 return $Candidate;
1806 }
1807 return "";
1808}
1809
1810sub get_CmdPath($)
1811{
1812 my $Name = $_[0];
1813 return "" if(not $Name);
1814 if(defined $Cache{"get_CmdPath"}{$Name}) {
1815 return $Cache{"get_CmdPath"}{$Name};
1816 }
1817 my %BinUtils = map {$_=>1} (
1818 "c++filt",
1819 "objdump",
1820 "readelf"
1821 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001822 if($BinUtils{$Name} and $GCC_PATH)
1823 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001824 if(my $Dir = get_dirname($GCC_PATH)) {
1825 $TargetTools{$Dir}=1;
1826 }
1827 }
1828 my $Path = search_Tools($Name);
1829 if(not $Path and $OSgroup eq "windows") {
1830 $Path = search_Tools($Name.".exe");
1831 }
1832 if(not $Path and $BinUtils{$Name})
1833 {
1834 if($CrossPrefix)
1835 { # user-defined prefix
1836 $Path = search_Cmd($CrossPrefix."-".$Name);
1837 }
1838 }
1839 if(not $Path and $BinUtils{$Name})
1840 {
1841 if(my $Candidate = synch_Cmd($Name))
1842 { # synch with GCC
1843 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001844 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001845 if(-f $Candidate) {
1846 $Path = $Candidate;
1847 }
1848 }
1849 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001850 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001851 $Path = $Candidate;
1852 }
1853 }
1854 }
1855 if(not $Path) {
1856 $Path = search_Cmd($Name);
1857 }
1858 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001859 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001860 $Path=search_Cmd($Name.".exe");
1861 }
1862 if($Path=~/\s/) {
1863 $Path = "\"".$Path."\"";
1864 }
1865 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1866}
1867
1868sub search_Cmd($)
1869{
1870 my $Name = $_[0];
1871 return "" if(not $Name);
1872 if(defined $Cache{"search_Cmd"}{$Name}) {
1873 return $Cache{"search_Cmd"}{$Name};
1874 }
1875 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1876 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1877 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001878 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001879 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001880 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001881 if(-f $CmdPath)
1882 {
1883 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001884 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001885 }
1886 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1887 }
1888 }
1889 return ($Cache{"search_Cmd"}{$Name} = "");
1890}
1891
1892sub get_CmdPath_Default($)
1893{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001894 return "" if(not $_[0]);
1895 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1896 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001897 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001898 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1899}
1900
1901sub get_CmdPath_Default_I($)
1902{ # search in PATH
1903 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001904 if($Name=~/find/)
1905 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001906 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001907 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001908 }
1909 }
1910 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001911 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001912 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001913 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001914 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001915 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001916 if($OSgroup eq "windows")
1917 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001918 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001919 return $Name;
1920 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001921 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001922 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001923 {
1924 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001925 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001926 }
1927 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001928 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001929}
1930
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001931sub classifyPath($)
1932{
1933 my $Path = $_[0];
1934 if($Path=~/[\*\[]/)
1935 { # wildcard
1936 $Path=~s/\*/.*/g;
1937 $Path=~s/\\/\\\\/g;
1938 return ($Path, "Pattern");
1939 }
1940 elsif($Path=~/[\/\\]/)
1941 { # directory or relative path
1942 return (path_format($Path, $OSgroup), "Path");
1943 }
1944 else {
1945 return ($Path, "Name");
1946 }
1947}
1948
1949sub readDescriptor($$)
1950{
1951 my ($LibVersion, $Content) = @_;
1952 return if(not $LibVersion);
1953 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1954 if(not $Content) {
1955 exitStatus("Error", "$DName is empty");
1956 }
1957 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001958 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001959 }
1960 $Content=~s/\/\*(.|\n)+?\*\///g;
1961 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001962
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001963 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1964 if($TargetVersion{$LibVersion}) {
1965 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1966 }
1967 if(not $Descriptor{$LibVersion}{"Version"}) {
1968 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1969 }
1970 if($Content=~/{RELPATH}/)
1971 {
1972 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1973 $Content =~ s/{RELPATH}/$RelDir/g;
1974 }
1975 else
1976 {
1977 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1978 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1979 }
1980 }
1981
1982 if(not $CheckObjectsOnly_Opt)
1983 {
1984 my $DHeaders = parseTag(\$Content, "headers");
1985 if(not $DHeaders) {
1986 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1987 }
1988 elsif(lc($DHeaders) ne "none")
1989 { # append the descriptor headers list
1990 if($Descriptor{$LibVersion}{"Headers"})
1991 { # multiple descriptors
1992 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
1993 }
1994 else {
1995 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1996 }
1997 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1998 {
1999 if(not -e $Path) {
2000 exitStatus("Access_Error", "can't access \'$Path\'");
2001 }
2002 }
2003 }
2004 }
2005 if(not $CheckHeadersOnly_Opt)
2006 {
2007 my $DObjects = parseTag(\$Content, "libs");
2008 if(not $DObjects) {
2009 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
2010 }
2011 elsif(lc($DObjects) ne "none")
2012 { # append the descriptor libraries list
2013 if($Descriptor{$LibVersion}{"Libs"})
2014 { # multiple descriptors
2015 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
2016 }
2017 else {
2018 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
2019 }
2020 foreach my $Path (split(/\s*\n\s*/, $DObjects))
2021 {
2022 if(not -e $Path) {
2023 exitStatus("Access_Error", "can't access \'$Path\'");
2024 }
2025 }
2026 }
2027 }
2028 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
2029 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002030 if(not -d $Path) {
2031 exitStatus("Access_Error", "can't access directory \'$Path\'");
2032 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002033 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002034 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002035 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002036 }
2037 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
2038 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002039 if(not -d $Path) {
2040 exitStatus("Access_Error", "can't access directory \'$Path\'");
2041 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002042 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002043 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002044 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002045 }
2046 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
2047 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002048 if(not -d $Path) {
2049 exitStatus("Access_Error", "can't access directory \'$Path\'");
2050 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002051 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002052 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002053 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002054 $TargetTools{$Path}=1;
2055 }
2056 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
2057 $CrossPrefix = $Prefix;
2058 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002059 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002060 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
2061 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002062 if(not -d $Path) {
2063 exitStatus("Access_Error", "can't access directory \'$Path\'");
2064 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002065 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002066 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002067 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002068 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002069 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002070 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
2071 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002072 if(not -d $Path) {
2073 exitStatus("Access_Error", "can't access directory \'$Path\'");
2074 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002075 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002076 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002077 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002078 }
2079 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002080 { # skip some auto-generated include paths
2081 if(not is_abs($Path))
2082 {
2083 if(my $P = abs_path($Path)) {
2084 $Path = $P;
2085 }
2086 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002087 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002088 }
2089 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002090 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002091 my ($CPath, $Type) = classifyPath($Path);
2092 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002093 }
2094 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002095 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
2096 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002097 if($Option!~/\A\-(Wl|l|L)/)
2098 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002099 $CompilerOptions{$LibVersion} .= " ".$Option;
2100 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002101 }
2102 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
2103 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
2104 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002105 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002106 my ($CPath, $Type) = classifyPath($Path);
2107 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002108 }
2109 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
2110 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
2111 {
2112 my ($CPath, $Type) = classifyPath($Path);
2113 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
2114 }
2115 if(my $DDefines = parseTag(\$Content, "defines"))
2116 {
2117 if($Descriptor{$LibVersion}{"Defines"})
2118 { # multiple descriptors
2119 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
2120 }
2121 else {
2122 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
2123 }
2124 }
2125 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2126 {
2127 if($Order=~/\A(.+):(.+)\Z/) {
2128 $Include_Order{$LibVersion}{$1} = $2;
2129 }
2130 }
2131 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2132 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002133 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002134 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2135 }
2136 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2137 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002138 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002139 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2140 }
2141 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2142 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2143 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002144 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2145 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2146 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002147 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2148 $SkipConstants{$LibVersion}{$Constant} = 1;
2149 }
2150 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2151 {
2152 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002153 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002154 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2155 }
2156 else {
2157 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2158 }
2159 }
2160}
2161
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002162sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002163{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002164 my $CodeRef = shift(@_);
2165 my $Tag = shift(@_);
2166 if(not $Tag or not $CodeRef) {
2167 return undef;
2168 }
2169 my $Sp = 0;
2170 if(@_) {
2171 $Sp = shift(@_);
2172 }
2173 my $Start = index(${$CodeRef}, "<$Tag>");
2174 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002175 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002176 my $End = index(${$CodeRef}, "</$Tag>");
2177 if($End!=-1)
2178 {
2179 my $TS = length($Tag)+3;
2180 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2181 substr($Content, 0, $TS-1, ""); # cut start tag
2182 substr($Content, -$TS, $TS, ""); # cut end tag
2183 if(not $Sp)
2184 {
2185 $Content=~s/\A\s+//g;
2186 $Content=~s/\s+\Z//g;
2187 }
2188 if(substr($Content, 0, 1) ne "<") {
2189 $Content = xmlSpecChars_R($Content);
2190 }
2191 return $Content;
2192 }
2193 }
2194 return undef;
2195}
2196
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002197sub getInfo($)
2198{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002199 my $DumpPath = $_[0];
2200 return if(not $DumpPath or not -f $DumpPath);
2201
2202 readTUDump($DumpPath);
2203
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002204 # processing info
2205 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002206
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002207 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002208 setAnonTypedef_All();
2209 }
2210
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002211 getTypeInfo_All();
2212 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002213 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002214 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002215 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002216
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002217 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002218 %LibInfo = ();
2219 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002220 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002221 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002222 %TemplateDecl = ();
2223 %StdCxxTypedef = ();
2224 %MissedTypedef = ();
2225 %Typedef_Tr = ();
2226 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002227 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002228
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002229 # clean cache
2230 delete($Cache{"getTypeAttr"});
2231 delete($Cache{"getTypeDeclId"});
2232
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002233 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002234 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002235 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002236 }
2237 else
2238 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002239 if($BinaryOnly and not $ExtendedCheck)
2240 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002241 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002242 }
2243 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002244 remove_Unused($Version, "Extended");
2245 }
2246 }
2247
2248 if($CheckInfo)
2249 {
2250 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2251 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2252 }
2253
2254 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2255 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002256 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002257 }
2258
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002259 if($Debug) {
2260 # debugMangling($Version);
2261 }
2262}
2263
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002264sub readTUDump($)
2265{
2266 my $DumpPath = $_[0];
2267
2268 open(TU_DUMP, $DumpPath);
2269 local $/ = undef;
2270 my $Content = <TU_DUMP>;
2271 close(TU_DUMP);
2272
2273 unlink($DumpPath);
2274
2275 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002276 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002277
2278 # clean memory
2279 undef $Content;
2280
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002281 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002282
2283 foreach (0 .. $#Lines)
2284 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002285 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002286 { # get a number and attributes of a node
2287 next if(not $NodeType{$2});
2288 $LibInfo{$Version}{"info_type"}{$1}=$2;
2289 $LibInfo{$Version}{"info"}{$1}=$3;
2290 }
2291
2292 # clean memory
2293 delete($Lines[$_]);
2294 }
2295
2296 # clean memory
2297 undef @Lines;
2298}
2299
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002300sub simplifyConstants()
2301{
2302 foreach my $Constant (keys(%{$Constants{$Version}}))
2303 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002304 if(defined $Constants{$Version}{$Constant}{"Header"})
2305 {
2306 my $Value = $Constants{$Version}{$Constant}{"Value"};
2307 if(defined $EnumConstants{$Version}{$Value}) {
2308 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2309 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002310 }
2311 }
2312}
2313
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002314sub simplifyNames()
2315{
2316 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2317 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002318 if($Typedef_Eq{$Version}{$Base}) {
2319 next;
2320 }
2321 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2322 if($#Translations==0)
2323 {
2324 if(length($Translations[0])<=length($Base)) {
2325 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2326 }
2327 }
2328 else
2329 { # select most appropriate
2330 foreach my $Tr (@Translations)
2331 {
2332 if($Base=~/\A\Q$Tr\E/)
2333 {
2334 $Typedef_Eq{$Version}{$Base} = $Tr;
2335 last;
2336 }
2337 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002338 }
2339 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002340 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002341 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002342 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002343 if(not $TypeName) {
2344 next;
2345 }
2346 next if(index($TypeName,"<")==-1);# template instances only
2347 if($TypeName=~/>(::\w+)+\Z/)
2348 { # skip unused types
2349 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002350 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002351 foreach my $Base (sort {length($b)<=>length($a)}
2352 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002353 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002354 next if(not $Base);
2355 next if(index($TypeName,$Base)==-1);
2356 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002357 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002358 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002359 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2360 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2361 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002362 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002363 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2364 {
2365 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2366 {
2367 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2368 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002369 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002370 }
2371 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002372 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002373 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002374 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002375 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002376 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2377 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002378 }
2379}
2380
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002381sub setAnonTypedef_All()
2382{
2383 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2384 {
2385 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2386 {
2387 if(isAnon(getNameByInfo($InfoId))) {
2388 $TypedefToAnon{getTypeId($InfoId)} = 1;
2389 }
2390 }
2391 }
2392}
2393
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002394sub setTemplateParams_All()
2395{
2396 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2397 {
2398 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2399 setTemplateParams($_);
2400 }
2401 }
2402}
2403
2404sub setTemplateParams($)
2405{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002406 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002407 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002408 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002409 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002410 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002411 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002412 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002413 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002414 setTemplateInstParams($_[0], $TmplInst_Id);
2415 }
2416 }
2417
2418 $BasicTemplate{$Version}{$Tid} = $_[0];
2419
2420 if(my $Prms = getTreeAttr_Prms($_[0]))
2421 {
2422 if(my $Valu = getTreeAttr_Valu($Prms))
2423 {
2424 my $Vector = getTreeVec($Valu);
2425 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2426 {
2427 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2428 {
2429 if(my $Name = getNameByInfo($Val))
2430 {
2431 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2432 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2433 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2434 }
2435 else {
2436 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2437 }
2438 }
2439 }
2440 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002441 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002442 }
2443 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002444 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002445 {
2446 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2447 {
2448 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002449 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002450 }
2451 }
2452 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002453}
2454
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002455sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002456{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002457 my ($Tmpl, $Inst) = @_;
2458
2459 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002460 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002461 my ($Params_InfoId, $ElemId) = ();
2462 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2463 $Params_InfoId = $1;
2464 }
2465 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2466 $ElemId = $1;
2467 }
2468 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002469 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002470 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2471 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2472 {
2473 my ($PPos, $PTypeId) = ($1, $2);
2474 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2475 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002476 if($PType eq "template_type_parm") {
2477 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002478 }
2479 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002480 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2481 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002482 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002483 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002484 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002485 else
2486 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002487 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002488 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002489 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002490 }
2491 }
2492 }
2493}
2494
2495sub getTypeDeclId($)
2496{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002497 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002498 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002499 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2500 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2501 }
2502 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2503 {
2504 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2505 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2506 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002507 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002508 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002509 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002510}
2511
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002512sub getTypeInfo_All()
2513{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002514 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002515 { # support for GCC < 4.5
2516 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2517 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2518 # FIXME: check GCC versions
2519 addMissedTypes_Pre();
2520 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002521
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002522 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002523 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002524 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2525 if($IType=~/_type\Z/ and $IType ne "function_type"
2526 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002527 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002528 }
2529 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002530
2531 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002532 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002533 "Name" => "...",
2534 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002535 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002536 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002537 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002538
2539 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002540 { # support for GCC < 4.5
2541 addMissedTypes_Post();
2542 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002543
2544 if($ADD_TMPL_INSTANCES)
2545 {
2546 # templates
2547 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2548 {
2549 if(defined $TemplateMap{$Version}{$Tid}
2550 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2551 {
2552 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2553 {
2554 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2555 {
2556 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2557 {
2558 if(my %MAttr = getTypeAttr($MembTypeId))
2559 {
2560 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2561 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2562 }
2563 }
2564 }
2565 }
2566 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2567 {
2568 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2569 {
2570 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2571
2572 if($NBid ne $Bid)
2573 {
2574 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2575 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2576 }
2577 }
2578 }
2579 }
2580 }
2581 }
2582}
2583
2584sub createType($$)
2585{
2586 my ($Attr, $LibVersion) = @_;
2587 my $NewId = ++$MAX_ID;
2588
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002589 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002590 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002591 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002592
2593 return "$NewId";
2594}
2595
2596sub instType($$$)
2597{ # create template instances
2598 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002599
2600 if(not $TypeInfo{$LibVersion}{$Tid}) {
2601 return undef;
2602 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002603 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2604
2605 foreach my $Key (sort keys(%{$Map}))
2606 {
2607 if(my $Val = $Map->{$Key})
2608 {
2609 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2610
2611 if(defined $Attr->{"NameSpace"}) {
2612 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2613 }
2614 foreach (keys(%{$Attr->{"TParam"}})) {
2615 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2616 }
2617 }
2618 else
2619 { # remove absent
2620 # _Traits, etc.
2621 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002622 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002623 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2624 }
2625 foreach (keys(%{$Attr->{"TParam"}}))
2626 {
2627 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2628 delete($Attr->{"TParam"}{$_});
2629 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002630 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002631 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2632 }
2633 }
2634 }
2635 }
2636
2637 my $Tmpl = 0;
2638
2639 if(defined $Attr->{"TParam"})
2640 {
2641 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2642 {
2643 my $PName = $Attr->{"TParam"}{$_}{"name"};
2644
2645 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2646 {
2647 my %Base = get_BaseType($PTid, $LibVersion);
2648
2649 if($Base{"Type"} eq "TemplateParam"
2650 or defined $Base{"Template"})
2651 {
2652 $Tmpl = 1;
2653 last
2654 }
2655 }
2656 }
2657 }
2658
2659 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2660 return "$Id";
2661 }
2662 else
2663 {
2664 if(not $Tmpl) {
2665 delete($Attr->{"Template"});
2666 }
2667
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002668 my $New = createType($Attr, $LibVersion);
2669
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002670 my %EMap = ();
2671 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2672 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2673 }
2674 foreach (keys(%{$Map})) {
2675 $EMap{$_} = $Map->{$_};
2676 }
2677
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002678 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2679 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002680 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002681 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002682 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002683 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002684 {
2685 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2686
2687 if($NBid ne $Bid)
2688 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002689 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2690 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002691 }
2692 }
2693 }
2694
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002695 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002696 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002697 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2698 {
2699 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2700 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2701 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002702 }
2703 }
2704
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002705 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002706 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002707 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2708 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002709 }
2710 }
2711
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002712 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2713 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002714 }
2715
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002716 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002717 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002718}
2719
2720sub addMissedTypes_Pre()
2721{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002722 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002723 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2724 { # detecting missed typedefs
2725 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2726 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002727 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002728 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002729 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002730 if($TypeType eq "Unknown")
2731 { # template_type_parm
2732 next;
2733 }
2734 my $TypeDeclId = getTypeDeclId($TypeId);
2735 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2736 my $TypedefName = getNameByInfo($MissedTDid);
2737 next if(not $TypedefName);
2738 next if($TypedefName eq "__float80");
2739 next if(isAnon($TypedefName));
2740 if(not $TypeDeclId
2741 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002742 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002743 }
2744 }
2745 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002746 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002747 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002748 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002749 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002750 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002751 next;
2752 }
2753 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002754 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002755 if(not $TypedefName) {
2756 next;
2757 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002758 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002759 my %MissedInfo = ( # typedef info
2760 "Name" => $TypedefName,
2761 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002762 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002763 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002764 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002765 my ($H, $L) = getLocation($MissedTDid);
2766 $MissedInfo{"Header"} = $H;
2767 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002768 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002769 { # other types
2770 next;
2771 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002772 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002773 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002774 next;
2775 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002776 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002777 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002778 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002779 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002780 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002781 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002782 next;
2783 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002784 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002785 next;
2786 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002787 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002788 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002789 next;
2790 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002791 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002792 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002793 next;
2794 }
2795 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002796
2797 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2798
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002799 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002800 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002801 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002802 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002803 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002804
2805 # add missed & remove other
2806 $TypeInfo{$Version} = \%AddTypes;
2807 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002808}
2809
2810sub addMissedTypes_Post()
2811{
2812 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2813 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002814 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2815 {
2816 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2817 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2818 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2819 }
2820 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002821 }
2822}
2823
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002824sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002825{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002826 my $TypeId = $_[0];
2827 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2828 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002829 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002830 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002831 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002832}
2833
2834sub getArraySize($$)
2835{
2836 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002837 if(my $Size = getSize($TypeId))
2838 {
2839 my $Elems = $Size/$BYTE_SIZE;
2840 while($BaseName=~s/\s*\[(\d+)\]//) {
2841 $Elems/=$1;
2842 }
2843 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2844 {
2845 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2846 $Elems/=$BasicSize;
2847 }
2848 }
2849 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002850 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002851 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002852}
2853
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002854sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002855{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002856 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002857 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002858 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2859 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002860 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002861 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2862 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2863 if(not $NodeType)
2864 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002865 return ();
2866 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002867 if($NodeType eq "tree_vec")
2868 {
2869 if($Pos!=$#Positions)
2870 { # select last vector of parameters ( ns<P1>::type<P2> )
2871 next;
2872 }
2873 }
2874 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2875 foreach my $P (@Params)
2876 {
2877 if($P eq "") {
2878 return ();
2879 }
2880 elsif($P ne "\@skip\@") {
2881 @TmplParams = (@TmplParams, $P);
2882 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002883 }
2884 }
2885 return @TmplParams;
2886}
2887
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002888sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002889{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002890 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002891 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002892 if(defined $TypeInfo{$Version}{$TypeId}
2893 and $TypeInfo{$Version}{$TypeId}{"Name"})
2894 { # already created
2895 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002896 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002897 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2898 { # incomplete type
2899 return ();
2900 }
2901 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2902
2903 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002904 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002905
2906 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2907 {
2908 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2909 {
2910 if($Info=~/qual[ ]*:/)
2911 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002912 my $NewId = ++$MAX_ID;
2913
2914 $MissedBase{$Version}{$TypeId} = "$NewId";
2915 $MissedBase_R{$Version}{$NewId} = $TypeId;
2916 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2917 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002918 }
2919 }
2920 $TypeAttr{"Type"} = "Typedef";
2921 }
2922 else {
2923 $TypeAttr{"Type"} = getTypeType($TypeId);
2924 }
2925
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002926 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2927 {
2928 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2929 { # local code
2930 return ();
2931 }
2932 }
2933
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002934 if($TypeAttr{"Type"} eq "Unknown") {
2935 return ();
2936 }
2937 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2938 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002939 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002940 if(my $TName = $TypeAttr{"Name"})
2941 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002942 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002943 $TName_Tid{$Version}{$TName} = $TypeId;
2944 return %TypeAttr;
2945 }
2946 else {
2947 return ();
2948 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002949 }
2950 elsif($TypeAttr{"Type"} eq "Array")
2951 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002952 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2953 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002954 return ();
2955 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002956 if(my $Algn = getAlgn($TypeId)) {
2957 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2958 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002959 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002960 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002961 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002962 if(not $BTAttr{"Name"}) {
2963 return ();
2964 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002965 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002966 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002967 if(my $Size = getSize($TypeId)) {
2968 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2969 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002970 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002971 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2972 }
2973 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002974 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002976 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002977 else
2978 {
2979 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002980 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002981 $TypeAttr{"Name"} = $1."[]".$2;
2982 }
2983 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002984 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002985 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002986 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002987 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002988 if($BTAttr{"Header"}) {
2989 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002990 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002991 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002992 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2993 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002994 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002995 return ();
2996 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002997 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002998 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002999 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003000 if($TypeAttr{"Name"})
3001 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003002 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003003
3004 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
3005 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003006 { # NOTE: register only one int: with built-in decl
3007 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3008 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3009 }
3010 }
3011 return %TypeAttr;
3012 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003013 else {
3014 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003015 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003016 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003017 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
3018 {
3019 %TypeAttr = getTrivialTypeAttr($TypeId);
3020 if($TypeAttr{"Name"})
3021 {
3022 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
3023 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3024 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3025 }
3026 return %TypeAttr;
3027 }
3028 else {
3029 return ();
3030 }
3031 }
3032 elsif($TypeAttr{"Type"} eq "SizeOf")
3033 {
3034 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
3035 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
3036 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
3037 if($TypeAttr{"Name"})
3038 {
3039 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
3040 return %TypeAttr;
3041 }
3042 else {
3043 return ();
3044 }
3045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003046 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003047 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003048 my ($BTid, $BTSpec) = selectBaseType($TypeId);
3049 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003050 return ();
3051 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003052 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003053 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003054 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003055 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003056 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003057 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003058 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003060 }
3061 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003062 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003063 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003064 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003065 return ();
3066 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003067 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003068 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003069 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003070 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003071 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003072 }
3073 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003074 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003075 {
3076 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003077 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003078 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003079 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003080 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
3081 }
3082 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003083 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003084 }
3085 }
3086 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003087 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003088 }
3089 if($TypeAttr{"Type"} eq "Typedef")
3090 {
3091 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003092
3093 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
3094 return ();
3095 }
3096
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003097 if(isAnon($TypeAttr{"Name"}))
3098 { # anon typedef to anon type: ._N
3099 return ();
3100 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003101
3102 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
3103 { # artificial typedef of "struct X" to "X"
3104 $TypeAttr{"Artificial"} = 1;
3105 }
3106
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003107 if(my $NS = getNameSpace($TypeDeclId))
3108 {
3109 my $TypeName = $TypeAttr{"Name"};
3110 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
3111 { # "some_type" is the typedef to "struct some_type" in C++
3112 if($3) {
3113 $TypeAttr{"Name"} = $3."::".$TypeName;
3114 }
3115 }
3116 else
3117 {
3118 $TypeAttr{"NameSpace"} = $NS;
3119 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003120
3121 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
3122 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
3123 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003124 if($BTAttr{"NameSpace"}
3125 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003126 { # types like "std::fpos<__mbstate_t>" are
3127 # not covered by typedefs in the TU dump
3128 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003129 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3130 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003131 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003132 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003133 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003134 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003135 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003136 }
3137 }
3138 }
3139 }
3140 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003141 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003142 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003143 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003144 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3145 { # typedef int*const TYPEDEF; // first
3146 # int foo(TYPEDEF p); // const is optimized out
3147 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3148 if($BTAttr{"Name"}=~/</)
3149 {
3150 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3151 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3152 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003153 }
3154 }
3155 }
3156 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3157 }
3158 if(not $TypeAttr{"Size"})
3159 {
3160 if($TypeAttr{"Type"} eq "Pointer") {
3161 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3162 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003163 elsif($BTAttr{"Size"}) {
3164 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003165 }
3166 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003167 if(my $Algn = getAlgn($TypeId)) {
3168 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3169 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003170 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003171 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3172 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003173 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003174 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003175 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003176 { # typedef to "class Class"
3177 # should not be registered in TName_Tid
3178 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3179 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003181 }
3182 return %TypeAttr;
3183 }
3184}
3185
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003186sub getTreeVec($)
3187{
3188 my %Vector = ();
3189 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3190 {
3191 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3192 { # string length is N-1 because of the null terminator
3193 $Vector{$1} = $2;
3194 }
3195 }
3196 return \%Vector;
3197}
3198
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003199sub get_TemplateParam($$)
3200{
3201 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003202 return () if(not $Type_Id);
3203 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3204 return () if(not $NodeType);
3205 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003206 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003207 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003208 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003209 my $Num = getNodeIntCst($Type_Id);
3210 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003211 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003212 }
3213 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003214 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003215 }
3216 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003217 elsif($NodeType eq "string_cst") {
3218 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003219 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003220 elsif($NodeType eq "tree_vec")
3221 {
3222 my $Vector = getTreeVec($Type_Id);
3223 my @Params = ();
3224 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3225 {
3226 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3227 push(@Params, $P2);
3228 }
3229 }
3230 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003231 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003232 elsif($NodeType eq "parm_decl")
3233 {
3234 (getNameByInfo($Type_Id));
3235 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003236 else
3237 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003238 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003239 my $PName = $ParamAttr{"Name"};
3240 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003241 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003242 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003243 if($PName=~/\>/)
3244 {
3245 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003246 $PName = $Cover;
3247 }
3248 }
3249 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003250 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003251 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3252 # template<typename _Key, typename _Compare = std::less<_Key>
3253 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3254 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3255 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3256 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003257 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003258 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003259 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003260 }
3261}
3262
3263sub cover_stdcxx_typedef($)
3264{
3265 my $TypeName = $_[0];
3266 if(my @Covers = sort {length($a)<=>length($b)}
3267 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3268 { # take the shortest typedef
3269 # FIXME: there may be more than
3270 # one typedefs to the same type
3271 return $Covers[0];
3272 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003273 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003274 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3275 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3276 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003277 if(my $Cover = $Covers[0])
3278 {
3279 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3280 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3281 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003282 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003283 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003284}
3285
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003286sub getNodeIntCst($)
3287{
3288 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003289 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003290 if($EnumMembName_Id{$Version}{$CstId}) {
3291 return $EnumMembName_Id{$Version}{$CstId};
3292 }
3293 elsif((my $Value = getTreeValue($CstId)) ne "")
3294 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003295 if($Value eq "0")
3296 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003297 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003298 return "false";
3299 }
3300 else {
3301 return "0";
3302 }
3303 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003304 elsif($Value eq "1")
3305 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003306 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003307 return "true";
3308 }
3309 else {
3310 return "1";
3311 }
3312 }
3313 else {
3314 return $Value;
3315 }
3316 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003317 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003318}
3319
3320sub getNodeStrCst($)
3321{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003322 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3323 {
3324 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003325 {
3326 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3327 { # string length is N-1 because of the null terminator
3328 return substr($1, 0, $2-1);
3329 }
3330 else
3331 { # identifier_node
3332 return substr($1, 0, $2);
3333 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003334 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003335 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003336 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003337}
3338
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003339sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003340{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003341 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003342 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3343 if($Type eq "FieldPtr") {
3344 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3345 }
3346 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3347 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003348 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003349 if($Type eq "MethodPtr")
3350 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003351 if(my $Size = getSize($TypeId))
3352 {
3353 $Size/=$BYTE_SIZE;
3354 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003355 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003356 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003357 if(my $Algn = getAlgn($TypeId)) {
3358 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3359 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003360 # Return
3361 if($Type eq "FieldPtr")
3362 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003363 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003364 if($ReturnAttr{"Name"}) {
3365 $MemPtrName .= $ReturnAttr{"Name"};
3366 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003367 $TypeAttr{"Return"} = $PtrId;
3368 }
3369 else
3370 {
3371 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3372 {
3373 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003374 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3375 if(not $ReturnAttr{"Name"})
3376 { # templates
3377 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003378 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003379 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003380 $TypeAttr{"Return"} = $ReturnTypeId;
3381 }
3382 }
3383 # Class
3384 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3385 {
3386 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003387 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003388 if($Class{"Name"}) {
3389 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3390 }
3391 else {
3392 $MemPtrName .= " (*)";
3393 }
3394 }
3395 else {
3396 $MemPtrName .= " (*)";
3397 }
3398 # Parameters
3399 if($Type eq "FuncPtr"
3400 or $Type eq "MethodPtr")
3401 {
3402 my @ParamTypeName = ();
3403 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3404 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003405 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003406 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003407 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003408 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003409 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3410 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003411 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003412 my $PTypeId = $1;
3413 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003414 if(not $ParamAttr{"Name"})
3415 { # templates (template_type_parm), etc.
3416 return ();
3417 }
3418 if($ParamAttr{"Name"} eq "void") {
3419 last;
3420 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003421 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003422 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003423 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003424 push(@ParamTypeName, $ParamAttr{"Name"});
3425 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003426 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3427 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003428 }
3429 else {
3430 last;
3431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003432 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003433 else {
3434 last;
3435 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003436 }
3437 }
3438 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3439 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003440 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003441 return %TypeAttr;
3442}
3443
3444sub getTreeTypeName($)
3445{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003446 my $TypeId = $_[0];
3447 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003448 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003449 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003450 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003451 if(my $Name = getNameByInfo($TypeId))
3452 { # bit_size_type
3453 return $Name;
3454 }
3455 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003456 return "unsigned int";
3457 }
3458 else {
3459 return "int";
3460 }
3461 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003462 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003463 return getNameByInfo($1);
3464 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003465 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003466 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003467}
3468
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003469sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003470{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003471 my $Ptd = pointTo($_[0]);
3472 return 0 if(not $Ptd);
3473 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003474 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003475 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3476 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003477 }
3478 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003479 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3480 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003481 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003482 if($InfoT1 eq "pointer_type"
3483 and $InfoT2 eq "function_type") {
3484 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003485 }
3486 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003487 return 0;
3488}
3489
3490sub isMethodPtr($)
3491{
3492 my $Ptd = pointTo($_[0]);
3493 return 0 if(not $Ptd);
3494 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3495 {
3496 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3497 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3498 and $Info=~/ ptrmem /) {
3499 return 1;
3500 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003501 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003502 return 0;
3503}
3504
3505sub isFieldPtr($)
3506{
3507 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3508 {
3509 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3510 and $Info=~/ ptrmem /) {
3511 return 1;
3512 }
3513 }
3514 return 0;
3515}
3516
3517sub pointTo($)
3518{
3519 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3520 {
3521 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3522 return $1;
3523 }
3524 }
3525 return "";
3526}
3527
3528sub getTypeTypeByTypeId($)
3529{
3530 my $TypeId = $_[0];
3531 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3532 {
3533 my $NType = $NodeType{$TType};
3534 if($NType eq "Intrinsic") {
3535 return $NType;
3536 }
3537 elsif(isFuncPtr($TypeId)) {
3538 return "FuncPtr";
3539 }
3540 elsif(isMethodPtr($TypeId)) {
3541 return "MethodPtr";
3542 }
3543 elsif(isFieldPtr($TypeId)) {
3544 return "FieldPtr";
3545 }
3546 elsif($NType ne "Other") {
3547 return $NType;
3548 }
3549 }
3550 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003551}
3552
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003553my %UnQual = (
3554 "r"=>"restrict",
3555 "v"=>"volatile",
3556 "c"=>"const",
3557 "cv"=>"const volatile"
3558);
3559
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003560sub getQual($)
3561{
3562 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003563 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3564 {
3565 my ($Qual, $To) = ();
3566 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3567 $Qual = $UnQual{$1};
3568 }
3569 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3570 $To = $1;
3571 }
3572 if($Qual and $To) {
3573 return ($Qual, $To);
3574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003575 }
3576 return ();
3577}
3578
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003579sub getQualType($)
3580{
3581 if($_[0] eq "const volatile") {
3582 return "ConstVolatile";
3583 }
3584 return ucfirst($_[0]);
3585}
3586
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003587sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003588{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003589 my $TypeId = $_[0];
3590 my $TypeDeclId = getTypeDeclId($TypeId);
3591 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003592 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003593 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3594 return "Typedef";
3595 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003596 }
3597 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3598 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003599 if(($Qual or $To) and $TypeDeclId
3600 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003601 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003602 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003603 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003604 elsif(not $MissedBase_R{$Version}{$TypeId}
3605 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003606 return "Typedef";
3607 }
3608 elsif($Qual)
3609 { # qualified types
3610 return getQualType($Qual);
3611 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003612
3613 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3614 { # typedef struct { ... } name
3615 $TypeTypedef{$Version}{$TypeId} = $1;
3616 }
3617
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003618 my $TypeType = getTypeTypeByTypeId($TypeId);
3619 if($TypeType eq "Struct")
3620 {
3621 if($TypeDeclId
3622 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3623 return "Template";
3624 }
3625 }
3626 return $TypeType;
3627}
3628
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003629sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003630{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003631 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003632 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003633 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3634 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3635 return 0;
3636 }
3637 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3638 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003639 if(my $TDid = getTypeDeclId($_[0]))
3640 {
3641 if(getTypeId($TDid) eq $_[0]
3642 and getNameByInfo($TDid))
3643 {
3644 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3645 return $1;
3646 }
3647 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003648 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003649 }
3650 }
3651 return 0;
3652}
3653
3654sub selectBaseType($)
3655{
3656 my $TypeId = $_[0];
3657 if(defined $MissedTypedef{$Version}{$TypeId})
3658 { # add missed typedefs
3659 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3660 return ($TypeId, "");
3661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003662 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003663 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3664 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003665
3666 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3667 my $MB = $MissedBase{$Version}{$TypeId};
3668
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003669 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003670 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003671 and (getTypeId($1) ne $TypeId)
3672 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003673 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003674 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003675 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003676 elsif($MB)
3677 { # add base
3678 return ($MB, "");
3679 }
3680 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003681 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003682 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003683 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003684 elsif($Qual or $To)
3685 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003686 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003687 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003688 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003689 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003690 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003691 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003693 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003694 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003695 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003696 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003697 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003698 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003699 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003700 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003701 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003702 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003703 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003704 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003705 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003706
3707 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003708}
3709
3710sub getSymbolInfo_All()
3711{
3712 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3713 { # reverse order
3714 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003715 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003716 }
3717 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003718
3719 if($ADD_TMPL_INSTANCES)
3720 {
3721 # templates
3722 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3723 {
3724 my %Map = ();
3725
3726 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3727 {
3728 if(defined $TemplateMap{$Version}{$ClassId})
3729 {
3730 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3731 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3732 }
3733 }
3734 }
3735
3736 if(defined $TemplateMap{$Version}{$Sid})
3737 {
3738 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3739 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3740 }
3741 }
3742
3743 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3744 {
3745 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3746 {
3747 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3748 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3749 }
3750 }
3751 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3752 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3753 }
3754 }
3755 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003756}
3757
3758sub getVarInfo_All()
3759{
3760 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3761 { # reverse order
3762 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003763 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003764 }
3765 }
3766}
3767
3768sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003769 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003770}
3771
3772sub getVarInfo($)
3773{
3774 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003775 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003776 {
3777 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3778 if($NSInfoType and $NSInfoType eq "function_decl") {
3779 return;
3780 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003781 }
3782 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3783 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3784 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3785 delete($SymbolInfo{$Version}{$InfoId});
3786 return;
3787 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003788 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003789 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003790 delete($SymbolInfo{$Version}{$InfoId});
3791 return;
3792 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003793 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3794 delete($SymbolInfo{$Version}{$InfoId});
3795 return;
3796 }
3797 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003798 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3799 {
3800 if($OSgroup eq "windows")
3801 { # cut the offset
3802 $MnglName=~s/\@\d+\Z//g;
3803 }
3804 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3805 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003806 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003807 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003808 { # validate mangled name
3809 delete($SymbolInfo{$Version}{$InfoId});
3810 return;
3811 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003812 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003813 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003814 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003815 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003816 }
3817 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3818 { # non-public global data
3819 delete($SymbolInfo{$Version}{$InfoId});
3820 return;
3821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003822 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003823 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003824 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003825 if(not defined $TypeInfo{$Version}{$Rid}
3826 or not $TypeInfo{$Version}{$Rid}{"Name"})
3827 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003828 delete($SymbolInfo{$Version}{$InfoId});
3829 return;
3830 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003831 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3832 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003833 if(defined $Val) {
3834 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003836 }
3837 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003838 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3839 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003840 if(not defined $TypeInfo{$Version}{$ClassId}
3841 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3842 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003843 delete($SymbolInfo{$Version}{$InfoId});
3844 return;
3845 }
3846 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003847 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3848 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003849 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003850 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003851 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003852 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003853 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003854 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003855 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003856 if(not $CheckHeadersOnly)
3857 {
3858 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3859 {
3860 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3861 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3862 {
3863 if(link_symbol($ShortName, $Version, "-Deps"))
3864 { # "const" global data is mangled as _ZL... in the TU dump
3865 # but not mangled when compiling a C shared library
3866 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3867 }
3868 }
3869 }
3870 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003871 if($COMMON_LANGUAGE{$Version} eq "C++")
3872 {
3873 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3874 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003875 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003876 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3877 }
3878 }
3879 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3880 { # try to mangle symbol (link with libraries)
3881 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3882 }
3883 if($OStarget eq "windows")
3884 {
3885 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3886 { # link MS C++ symbols from library with GCC symbols from headers
3887 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3888 }
3889 }
3890 }
3891 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3892 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3893 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003894 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3895 {
3896 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3897 { # non-target symbols
3898 delete($SymbolInfo{$Version}{$InfoId});
3899 return;
3900 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003901 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003902 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3903 {
3904 if(defined $MissedTypedef{$Version}{$Rid})
3905 {
3906 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3907 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3908 }
3909 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003910 }
3911 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003912 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003913 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3914 }
3915 if($ShortName=~/\A(_Z|\?)/) {
3916 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3917 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003918
3919 if($ExtraDump) {
3920 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3921 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003922}
3923
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003924sub isConstType($$)
3925{
3926 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003927 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003928 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003929 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003930 }
3931 return ($Base{"Type"} eq "Const");
3932}
3933
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003934sub getTrivialName($$)
3935{
3936 my ($TypeInfoId, $TypeId) = @_;
3937 my %TypeAttr = ();
3938 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3939 if(not $TypeAttr{"Name"}) {
3940 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3941 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003942 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003943 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003944 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003945 if(isAnon($TypeAttr{"Name"}))
3946 {
3947 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003948 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003949 { # searching for a first not anon scope
3950 if($NSId eq $NameSpaceId) {
3951 last;
3952 }
3953 else
3954 {
3955 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3956 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003957 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003958 last;
3959 }
3960 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003961 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003962 }
3963 }
3964 else
3965 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003966 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003967 {
3968 if($NameSpaceId ne $TypeId) {
3969 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3970 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003971 }
3972 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003973 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003974 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3975 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003976 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003977 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003978 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003979 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003980 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003981 if($TypeAttr{"NameSpace"}) {
3982 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3983 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003984 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003985 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3986 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003987 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003988 if(my @TParams = getTParams($TypeId, "Type")) {
3989 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3990 }
3991 else {
3992 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3993 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003994 }
3995 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3996}
3997
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003998sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003999{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004000 my $TypeId = $_[0];
4001 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004002
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004003 my %TypeAttr = ();
4004
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004005 if($TemplateDecl{$Version}{$TypeId})
4006 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004007 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004008 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004009
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004010 setTypeAccess($TypeId, \%TypeAttr);
4011 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
4012 if(isBuiltIn($TypeAttr{"Header"}))
4013 {
4014 delete($TypeAttr{"Header"});
4015 delete($TypeAttr{"Line"});
4016 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04004017
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004018 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004019 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
4020 if(not $TypeAttr{"Name"}) {
4021 return ();
4022 }
4023 if(not $TypeAttr{"NameSpace"}) {
4024 delete($TypeAttr{"NameSpace"});
4025 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004026
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04004027 if($TypeAttr{"Type"} eq "Intrinsic")
4028 {
4029 if(defined $TypeAttr{"Header"})
4030 {
4031 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
4032 { # support for SUSE 11.2
4033 # integer_type has srcp dump{1-2}.i
4034 delete($TypeAttr{"Header"});
4035 }
4036 }
4037 }
4038
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004039 my $Tmpl = undef;
4040
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004041 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004042 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004043 $Tmpl = $BasicTemplate{$Version}{$TypeId};
4044
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004045 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004046 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004047 foreach my $Pos (0 .. $#TParams)
4048 {
4049 my $Val = $TParams[$Pos];
4050 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
4051
4052 if(not defined $TypeAttr{"Template"})
4053 {
4054 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
4055
4056 if($Base{"Type"} eq "TemplateParam"
4057 or defined $Base{"Template"}) {
4058 $TypeAttr{"Template"} = 1;
4059 }
4060 }
4061
4062 if($Tmpl)
4063 {
4064 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
4065 {
4066 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
4067
4068 if($Val eq $Arg) {
4069 $TypeAttr{"Template"} = 1;
4070 }
4071 }
4072 }
4073 }
4074
4075 if($Tmpl)
4076 {
4077 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
4078 {
4079 if($Pos>$#TParams)
4080 {
4081 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
4082 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
4083 }
4084 }
4085 }
4086 }
4087
4088 if($ADD_TMPL_INSTANCES)
4089 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004090 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004091 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004092 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004093 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004094 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004095 {
4096 if(my $Flds = getTreeAttr_Flds($MainInst)) {
4097 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
4098 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004099 }
4100 if(not getTreeAttr_Binf($TypeId))
4101 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004102 if(my $Binf = getTreeAttr_Binf($MainInst)) {
4103 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
4104 }
4105 }
4106 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004107 }
4108 }
4109 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004110
4111 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
4112
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004113 if(my $Size = getSize($TypeId))
4114 {
4115 $Size = $Size/$BYTE_SIZE;
4116 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004117 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004118 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004119 {
4120 if($ExtraDump)
4121 {
4122 if(not defined $TypeAttr{"Memb"}
4123 and not $Tmpl)
4124 { # declaration only
4125 $TypeAttr{"Forward"} = 1;
4126 }
4127 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004128 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004129
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004130 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004131 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004132 {
4133 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004134 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004135 }
4136 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004137 or $TypeAttr{"Type"} eq "Class")
4138 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004139 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004140 if($Skip) {
4141 return ();
4142 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004143 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004144 if(my $Algn = getAlgn($TypeId)) {
4145 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4146 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004147 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004148
4149 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4150 {
4151 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004152 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004153 {
4154 if(not isAnon($TypeAttr{"Name"})) {
4155 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4156 }
4157 }
4158 }
4159
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004160 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004161 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4162 {
4163 my @Entries = split(/\n/, $VTable);
4164 foreach (1 .. $#Entries)
4165 {
4166 my $Entry = $Entries[$_];
4167 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004168 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004169 }
4170 }
4171 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004172
4173 if($TypeAttr{"Type"} eq "Enum")
4174 {
4175 if(not $TypeAttr{"NameSpace"})
4176 {
4177 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4178 {
4179 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004180 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004181 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004182 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004183 "Header"=>$TypeAttr{"Header"}
4184 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004185 if(isAnon($TypeAttr{"Name"}))
4186 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004187 if($ExtraDump
4188 or is_target_header($TypeAttr{"Header"}, $Version))
4189 {
4190 %{$Constants{$Version}{$MName}} = (
4191 "Value" => $MVal,
4192 "Header" => $TypeAttr{"Header"}
4193 );
4194 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004195 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004196 }
4197 }
4198 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004199 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004200 {
4201 if(defined $TypedefToAnon{$TypeId}) {
4202 $TypeAttr{"AnonTypedef"} = 1;
4203 }
4204 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004205
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004206 return %TypeAttr;
4207}
4208
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004209sub simplifyVTable($)
4210{
4211 my $Content = $_[0];
4212 if($Content=~s/ \[with (.+)]//)
4213 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4214 if(my @Elems = separate_Params($1, 0, 0))
4215 {
4216 foreach my $Elem (@Elems)
4217 {
4218 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4219 {
4220 my ($Arg, $Val) = ($1, $2);
4221
4222 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4223 $Content=~s/,\s*$Arg\b//g;
4224 }
4225 else {
4226 $Content=~s/\b$Arg\b/$Val/g;
4227 }
4228 }
4229 }
4230 }
4231 }
4232
4233 return $Content;
4234}
4235
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004236sub detect_lang($)
4237{
4238 my $TypeId = $_[0];
4239 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004240 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004241 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004242 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4243 }
4244 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004245 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004246 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004247 while($Fncs)
4248 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004249 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004250 return 1;
4251 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004252 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004253 }
4254 }
4255 return 0;
4256}
4257
4258sub setSpec($$)
4259{
4260 my ($TypeId, $TypeAttr) = @_;
4261 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4262 if($Info=~/\s+spec\s+/) {
4263 $TypeAttr->{"Spec"} = 1;
4264 }
4265}
4266
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004267sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004268{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004269 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004270 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004271 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004272 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004273 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004274 my $Pos = 0;
4275 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4276 {
4277 my ($Access, $BInfoId) = ($1, $2);
4278 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004279
4280 if($ClassId==$TypeId)
4281 { # class A<N>:public A<N-1>
4282 next;
4283 }
4284
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004285 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4286 if(not $CType or $CType eq "template_type_parm"
4287 or $CType eq "typename_type")
4288 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004289 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004291 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004292 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004293 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4294 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004295 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004296 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4297 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004298 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004299 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004300 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004301 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4302 }
4303 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004304 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004305 }
4306 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004307 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004308}
4309
4310sub getBinfClassId($)
4311{
4312 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4313 $Info=~/type[ ]*:[ ]*@(\d+) /;
4314 return $1;
4315}
4316
4317sub unmangledFormat($$)
4318{
4319 my ($Name, $LibVersion) = @_;
4320 $Name = uncover_typedefs($Name, $LibVersion);
4321 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4322 $Name=~s/\(\w+\)(\d)/$1/;
4323 return $Name;
4324}
4325
4326sub modelUnmangled($$)
4327{
4328 my ($InfoId, $Compiler) = @_;
4329 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4330 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4331 }
4332 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4333 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4334 $PureSignature = "~".$PureSignature;
4335 }
4336 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4337 {
4338 my (@Params, @ParamTypes) = ();
4339 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4340 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4341 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4342 }
4343 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4344 { # checking parameters
4345 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004346 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004347 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004348 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004349
4350 if($PName eq "this"
4351 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4352 {
4353 next;
4354 }
4355
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004356 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004357 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004358 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004359 }
4360 @ParamTypes = (@ParamTypes, $PTName);
4361 }
4362 if(@ParamTypes) {
4363 $PureSignature .= "(".join(", ", @ParamTypes).")";
4364 }
4365 else
4366 {
4367 if($Compiler eq "MSVC")
4368 {
4369 $PureSignature .= "(void)";
4370 }
4371 else
4372 { # GCC
4373 $PureSignature .= "()";
4374 }
4375 }
4376 $PureSignature = delete_keywords($PureSignature);
4377 }
4378 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4379 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004380 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004381 $PureSignature = $ClassName."::".$PureSignature;
4382 }
4383 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4384 $PureSignature = $NS."::".$PureSignature;
4385 }
4386 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4387 $PureSignature .= " const";
4388 }
4389 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4390 $PureSignature .= " volatile";
4391 }
4392 my $ShowReturn = 0;
4393 if($Compiler eq "MSVC"
4394 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4395 {
4396 $ShowReturn=1;
4397 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004398 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4399 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004400 {
4401 $ShowReturn=1;
4402 }
4403 if($ShowReturn)
4404 { # mangled names for template function specializations include return value
4405 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4406 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004407 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004408 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4409 $PureSignature = $ReturnName." ".$PureSignature;
4410 }
4411 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004412 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004413}
4414
4415sub mangle_symbol($$$)
4416{ # mangling for simple methods
4417 # see gcc-4.6.0/gcc/cp/mangle.c
4418 my ($InfoId, $LibVersion, $Compiler) = @_;
4419 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4420 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4421 }
4422 my $Mangled = "";
4423 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004424 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004425 }
4426 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004427 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004428 }
4429 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4430}
4431
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004432sub mangle_symbol_MSVC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004433{
4434 my ($InfoId, $LibVersion) = @_;
4435 return "";
4436}
4437
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004438sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004439{ # see gcc-4.6.0/gcc/cp/mangle.c
4440 my ($InfoId, $LibVersion) = @_;
4441 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004442 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004443 my %Repl = ();# SN_ replacements
4444 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4445 {
4446 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4447 if($MangledClass!~/\AN/) {
4448 $MangledClass = "N".$MangledClass;
4449 }
4450 else {
4451 $MangledClass=~s/E\Z//;
4452 }
4453 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4454 $MangledClass=~s/\AN/NV/;
4455 }
4456 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4457 $MangledClass=~s/\AN/NK/;
4458 }
4459 $Mangled .= $MangledClass;
4460 }
4461 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4462 { # mangled by name due to the absence of structured info
4463 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4464 if($MangledNS!~/\AN/) {
4465 $MangledNS = "N".$MangledNS;
4466 }
4467 else {
4468 $MangledNS=~s/E\Z//;
4469 }
4470 $Mangled .= $MangledNS;
4471 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004472 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004473 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004474 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004475 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004476 foreach (@TPos) {
4477 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4478 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004479 }
4480 elsif($TmplParams)
4481 { # remangling mode
4482 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004483 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004484 }
4485 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4486 $Mangled .= "C1";
4487 }
4488 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4489 $Mangled .= "D0";
4490 }
4491 elsif($ShortName)
4492 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004493 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4494 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004495 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004496 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004497 { # "const" global data is mangled as _ZL...
4498 $Mangled .= "L";
4499 }
4500 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004501 if($ShortName=~/\Aoperator(\W.*)\Z/)
4502 {
4503 my $Op = $1;
4504 $Op=~s/\A[ ]+//g;
4505 if(my $OpMngl = $OperatorMangling{$Op}) {
4506 $Mangled .= $OpMngl;
4507 }
4508 else { # conversion operator
4509 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4510 }
4511 }
4512 else {
4513 $Mangled .= length($ShortName).$ShortName;
4514 }
4515 if(@TParams)
4516 { # templates
4517 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004518 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004519 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4520 }
4521 $Mangled .= "E";
4522 }
4523 if(not $ClassId and @TParams) {
4524 add_substitution($ShortName, \%Repl, 0);
4525 }
4526 }
4527 if($ClassId or $NameSpace) {
4528 $Mangled .= "E";
4529 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004530 if(@TParams)
4531 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004532 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004533 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4534 }
4535 }
4536 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4537 {
4538 my @Params = ();
4539 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4540 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4541 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4542 }
4543 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4544 { # checking parameters
4545 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4546 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4547 }
4548 if(not @Params) {
4549 $Mangled .= "v";
4550 }
4551 }
4552 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4553 $Mangled = write_stdcxx_substitution($Mangled);
4554 if($Mangled eq "_Z") {
4555 return "";
4556 }
4557 return $Mangled;
4558}
4559
4560sub correct_incharge($$$)
4561{
4562 my ($InfoId, $LibVersion, $Mangled) = @_;
4563 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4564 {
4565 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004566 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004567 }
4568 }
4569 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4570 {
4571 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004572 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004573 }
4574 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004575 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004576 }
4577 }
4578 return $Mangled;
4579}
4580
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004581sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004582{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004583 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004584 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004585 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004586 return $Name;
4587 }
4588 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004589 while(my $CPos = find_center($TParams, "<"))
4590 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004591 $TParams = substr($TParams, $CPos);
4592 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004593 if($TParams=~s/\A<(.+)>\Z/$1/) {
4594 $Name=~s/<\Q$TParams\E>\Z//;
4595 }
4596 else
4597 { # error
4598 $TParams = "";
4599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004600 return ($Name, $TParams);
4601}
4602
4603sub get_sub_ns($)
4604{
4605 my $Name = $_[0];
4606 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004607 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004608 {
4609 push(@NS, substr($Name, 0, $CPos));
4610 $Name = substr($Name, $CPos);
4611 $Name=~s/\A:://;
4612 }
4613 return (join("::", @NS), $Name);
4614}
4615
4616sub mangle_ns($$$)
4617{
4618 my ($Name, $LibVersion, $Repl) = @_;
4619 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4620 {
4621 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4622 $Mangled=~s/\AN(.+)E\Z/$1/;
4623 return $Mangled;
4624
4625 }
4626 else
4627 {
4628 my ($MangledNS, $SubNS) = ("", "");
4629 ($SubNS, $Name) = get_sub_ns($Name);
4630 if($SubNS) {
4631 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4632 }
4633 $MangledNS .= length($Name).$Name;
4634 add_substitution($MangledNS, $Repl, 0);
4635 return $MangledNS;
4636 }
4637}
4638
4639sub mangle_param($$$)
4640{
4641 my ($PTid, $LibVersion, $Repl) = @_;
4642 my ($MPrefix, $Mangled) = ("", "");
4643 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004644 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004645 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004646 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004647 if(not $BaseType_Name) {
4648 return "";
4649 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004650 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004651 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004652 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4653 while($Suffix=~/(&|\*|const)\Z/)
4654 {
4655 if($Suffix=~s/[ ]*&\Z//) {
4656 $MPrefix .= "R";
4657 }
4658 if($Suffix=~s/[ ]*\*\Z//) {
4659 $MPrefix .= "P";
4660 }
4661 if($Suffix=~s/[ ]*const\Z//)
4662 {
4663 if($MPrefix=~/R|P/
4664 or $Suffix=~/&|\*/) {
4665 $MPrefix .= "K";
4666 }
4667 }
4668 if($Suffix=~s/[ ]*volatile\Z//) {
4669 $MPrefix .= "V";
4670 }
4671 #if($Suffix=~s/[ ]*restrict\Z//) {
4672 #$MPrefix .= "r";
4673 #}
4674 }
4675 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4676 $Mangled .= $Token;
4677 }
4678 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4679 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004680 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004681 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004682 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004683 foreach (@TPos) {
4684 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4685 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004686 }
4687 elsif($TmplParams)
4688 { # remangling mode
4689 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004690 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004691 }
4692 my $MangledNS = "";
4693 my ($SubNS, $SName) = get_sub_ns($ShortName);
4694 if($SubNS) {
4695 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4696 }
4697 $MangledNS .= length($SName).$SName;
4698 if(@TParams) {
4699 add_substitution($MangledNS, $Repl, 0);
4700 }
4701 $Mangled .= "N".$MangledNS;
4702 if(@TParams)
4703 { # templates
4704 $Mangled .= "I";
4705 foreach my $TParam (@TParams) {
4706 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4707 }
4708 $Mangled .= "E";
4709 }
4710 $Mangled .= "E";
4711 }
4712 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4713 {
4714 if($BaseType{"Type"} eq "MethodPtr") {
4715 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4716 }
4717 else {
4718 $Mangled .= "PF";
4719 }
4720 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4721 my @Params = keys(%{$BaseType{"Param"}});
4722 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4723 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4724 }
4725 if(not @Params) {
4726 $Mangled .= "v";
4727 }
4728 $Mangled .= "E";
4729 }
4730 elsif($BaseType{"Type"} eq "FieldPtr")
4731 {
4732 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4733 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4734 }
4735 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4736 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4737 {
4738 if($Mangled eq $Optimized)
4739 {
4740 if($ShortName!~/::/)
4741 { # remove "N ... E"
4742 if($MPrefix) {
4743 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4744 }
4745 else {
4746 $Mangled=~s/\AN(.+)E\Z/$1/g;
4747 }
4748 }
4749 }
4750 else {
4751 $Mangled = $Optimized;
4752 }
4753 }
4754 add_substitution($Mangled, $Repl, 1);
4755 return $Mangled;
4756}
4757
4758sub mangle_template_param($$$)
4759{ # types + literals
4760 my ($TParam, $LibVersion, $Repl) = @_;
4761 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4762 return mangle_param($TPTid, $LibVersion, $Repl);
4763 }
4764 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4765 { # class_name<1u>::method(...)
4766 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4767 }
4768 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4769 { # class_name<(signed char)1>::method(...)
4770 return "L".$IntrinsicMangling{$1}.$2."E";
4771 }
4772 elsif($TParam eq "true")
4773 { # class_name<true>::method(...)
4774 return "Lb1E";
4775 }
4776 elsif($TParam eq "false")
4777 { # class_name<true>::method(...)
4778 return "Lb0E";
4779 }
4780 else { # internal error
4781 return length($TParam).$TParam;
4782 }
4783}
4784
4785sub add_substitution($$$)
4786{
4787 my ($Value, $Repl, $Rec) = @_;
4788 if($Rec)
4789 { # subtypes
4790 my @Subs = ($Value);
4791 while($Value=~s/\A(R|P|K)//) {
4792 push(@Subs, $Value);
4793 }
4794 foreach (reverse(@Subs)) {
4795 add_substitution($_, $Repl, 0);
4796 }
4797 return;
4798 }
4799 return if($Value=~/\AS(\d*)_\Z/);
4800 $Value=~s/\AN(.+)E\Z/$1/g;
4801 return if(defined $Repl->{$Value});
4802 return if(length($Value)<=1);
4803 return if($StdcxxMangling{$Value});
4804 # check for duplicates
4805 my $Base = $Value;
4806 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4807 {
4808 my $Num = $Repl->{$Type};
4809 my $Replace = macro_mangle($Num);
4810 $Base=~s/\Q$Replace\E/$Type/;
4811 }
4812 if(my $OldNum = $Repl->{$Base})
4813 {
4814 $Repl->{$Value} = $OldNum;
4815 return;
4816 }
4817 my @Repls = sort {$b<=>$a} values(%{$Repl});
4818 if(@Repls) {
4819 $Repl->{$Value} = $Repls[0]+1;
4820 }
4821 else {
4822 $Repl->{$Value} = -1;
4823 }
4824 # register duplicates
4825 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004826 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004827 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4828 {
4829 next if($Base eq $Type);
4830 my $Num = $Repl->{$Type};
4831 my $Replace = macro_mangle($Num);
4832 $Base=~s/\Q$Type\E/$Replace/;
4833 $Repl->{$Base} = $Repl->{$Value};
4834 }
4835}
4836
4837sub macro_mangle($)
4838{
4839 my $Num = $_[0];
4840 if($Num==-1) {
4841 return "S_";
4842 }
4843 else
4844 {
4845 my $Code = "";
4846 if($Num<10)
4847 { # S0_, S1_, S2_, ...
4848 $Code = $Num;
4849 }
4850 elsif($Num>=10 and $Num<=35)
4851 { # SA_, SB_, SC_, ...
4852 $Code = chr(55+$Num);
4853 }
4854 else
4855 { # S10_, S11_, S12_
4856 $Code = $Num-26; # 26 is length of english alphabet
4857 }
4858 return "S".$Code."_";
4859 }
4860}
4861
4862sub write_stdcxx_substitution($)
4863{
4864 my $Mangled = $_[0];
4865 if($StdcxxMangling{$Mangled}) {
4866 return $StdcxxMangling{$Mangled};
4867 }
4868 else
4869 {
4870 my @Repls = keys(%StdcxxMangling);
4871 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4872 foreach my $MangledType (@Repls)
4873 {
4874 my $Replace = $StdcxxMangling{$MangledType};
4875 #if($Mangled!~/$Replace/) {
4876 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4877 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4878 #}
4879 }
4880 }
4881 return $Mangled;
4882}
4883
4884sub write_substitution($$)
4885{
4886 my ($Mangled, $Repl) = @_;
4887 if(defined $Repl->{$Mangled}
4888 and my $MnglNum = $Repl->{$Mangled}) {
4889 $Mangled = macro_mangle($MnglNum);
4890 }
4891 else
4892 {
4893 my @Repls = keys(%{$Repl});
4894 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4895 # FIXME: how to apply replacements? by num or by pos
4896 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4897 foreach my $MangledType (@Repls)
4898 {
4899 my $Replace = macro_mangle($Repl->{$MangledType});
4900 if($Mangled!~/$Replace/) {
4901 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4902 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4903 }
4904 }
4905 }
4906 return $Mangled;
4907}
4908
4909sub delete_keywords($)
4910{
4911 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004912 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004913 return $TypeName;
4914}
4915
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004916sub uncover_typedefs($$)
4917{
4918 my ($TypeName, $LibVersion) = @_;
4919 return "" if(not $TypeName);
4920 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4921 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4922 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004923 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004924 while($TypeName_New ne $TypeName_Pre)
4925 {
4926 $TypeName_Pre = $TypeName_New;
4927 my $TypeName_Copy = $TypeName_New;
4928 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004929 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004930 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004931 if(not $Intrinsic_Keywords{$1}) {
4932 $Words{$1} = 1;
4933 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004934 }
4935 foreach my $Word (keys(%Words))
4936 {
4937 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4938 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004939 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004940 if($BaseType_Name=~/\([\*]+\)/)
4941 { # FuncPtr
4942 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4943 {
4944 my $Type_Suffix = $1;
4945 $TypeName_New = $BaseType_Name;
4946 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004947 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004948 }
4949 }
4950 }
4951 else
4952 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004953 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004954 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004955 }
4956 }
4957 }
4958 }
4959 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4960}
4961
4962sub isInternal($)
4963{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004964 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4965 {
4966 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4967 {
4968 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4969 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4970 return 1;
4971 }
4972 }
4973 }
4974 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004975}
4976
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004977sub getDataVal($$)
4978{
4979 my ($InfoId, $TypeId) = @_;
4980 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4981 {
4982 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4983 {
4984 if(defined $LibInfo{$Version}{"info_type"}{$1}
4985 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004986 {
4987 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004988 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004989 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4990 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004991 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004992 if(my $Addr = getTreeAttr_Op($1)) {
4993 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004994 }
4995 }
4996 }
4997 }
4998 else {
4999 return getInitVal($1, $TypeId);
5000 }
5001 }
5002 }
5003 return undef;
5004}
5005
5006sub getInitVal($$)
5007{
5008 my ($InfoId, $TypeId) = @_;
5009 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
5010 {
5011 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
5012 {
5013 if($InfoType eq "integer_cst")
5014 {
5015 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005016 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005017 { # characters
5018 $Val = chr($Val);
5019 }
5020 return $Val;
5021 }
5022 elsif($InfoType eq "string_cst") {
5023 return getNodeStrCst($InfoId);
5024 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005025 elsif($InfoType eq "var_decl")
5026 {
5027 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
5028 return $Name;
5029 }
5030 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005031 }
5032 }
5033 return undef;
5034}
5035
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005036sub set_Class_And_Namespace($)
5037{
5038 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005039 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005040 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005041 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005042 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005043 my $NSInfoId = $1;
5044 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
5045 {
5046 if($InfoType eq "namespace_decl") {
5047 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
5048 }
5049 elsif($InfoType eq "record_type") {
5050 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
5051 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005052 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005053 }
5054 }
5055 if($SymbolInfo{$Version}{$InfoId}{"Class"}
5056 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005057 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005058 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005059 { # skip
5060 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005061 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005062 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005063
5064 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005065}
5066
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005067sub debugMangling($)
5068{
5069 my $LibVersion = $_[0];
5070 my %Mangled = ();
5071 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
5072 {
5073 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
5074 {
5075 if($Mngl=~/\A(_Z|\?)/) {
5076 $Mangled{$Mngl}=$InfoId;
5077 }
5078 }
5079 }
5080 translateSymbols(keys(%Mangled), $LibVersion);
5081 foreach my $Mngl (keys(%Mangled))
5082 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005083 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
5084 my $U2 = $tr_name{$Mngl};
5085 if($U1 ne $U2) {
5086 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005087 }
5088 }
5089}
5090
5091sub linkSymbol($)
5092{ # link symbols from shared libraries
5093 # with the symbols from header files
5094 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005095 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005096 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005097 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5098 or $EMERGENCY_MODE_48)
5099 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
5100 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
5101 # GCC 4.8 doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005102 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005103 {
5104 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
5105 return correct_incharge($InfoId, $Version, $Mangled);
5106 }
5107 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005108 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005109 or not $BinaryOnly
5110 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005111 { # 1. --headers-only mode
5112 # 2. not mangled src-only symbols
5113 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
5114 return $Mangled;
5115 }
5116 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005117 }
5118 return "";
5119}
5120
5121sub setLanguage($$)
5122{
5123 my ($LibVersion, $Lang) = @_;
5124 if(not $UserLang) {
5125 $COMMON_LANGUAGE{$LibVersion} = $Lang;
5126 }
5127}
5128
5129sub getSymbolInfo($)
5130{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005131 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005132 if(isInternal($InfoId)) {
5133 return;
5134 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005135 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5136 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005137 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5138 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005139 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005140 return;
5141 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005142 setFuncAccess($InfoId);
5143 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005144 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5145 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005146 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005147 return;
5148 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005149
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005150 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005151 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005152 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005153 if(not defined $TypeInfo{$Version}{$Return}
5154 or not $TypeInfo{$Version}{$Return}{"Name"})
5155 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005156 delete($SymbolInfo{$Version}{$InfoId});
5157 return;
5158 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005159 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005160 }
5161 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5162 {
5163 if(defined $MissedTypedef{$Version}{$Rid})
5164 {
5165 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5166 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5167 }
5168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005169 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005170 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5171 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005172 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005173 my $Orig = getFuncOrig($InfoId);
5174 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005175 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5176 {
5177 delete($SymbolInfo{$Version}{$InfoId});
5178 return;
5179 }
5180
5181 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005182 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005183 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005184 return;
5185 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005186
5187 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005188 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005189 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5190
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005191 my @TParams = getTParams($Orig, "Func");
5192 if(not @TParams)
5193 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005194 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005195 return;
5196 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005197 foreach my $Pos (0 .. $#TParams)
5198 {
5199 my $Val = $TParams[$Pos];
5200 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5201
5202 if($Tmpl)
5203 {
5204 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5205 {
5206 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5207 }
5208 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005209 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005210
5211 if($Tmpl)
5212 {
5213 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5214 {
5215 if($Pos>$#TParams)
5216 {
5217 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5218 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5219 }
5220 }
5221 }
5222
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005223 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5224 { # operator<< <T>, operator>> <T>
5225 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5226 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005227 if(@TParams) {
5228 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5229 }
5230 else {
5231 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5232 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005233 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005234 }
5235 else
5236 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005237 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005238 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005239 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5240 {
5241 if($OSgroup eq "windows")
5242 { # cut the offset
5243 $MnglName=~s/\@\d+\Z//g;
5244 }
5245 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5246
5247 # NOTE: mangling of some symbols may change depending on GCC version
5248 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5249 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5250 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005251
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005252 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005253 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005254 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005255 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005256 return;
5257 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005258 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005259 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005260 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005261 if($Skip)
5262 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005263 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005264 return;
5265 }
5266 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005267 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5268 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5269 }
5270
5271 if(set_Class_And_Namespace($InfoId))
5272 {
5273 delete($SymbolInfo{$Version}{$InfoId});
5274 return;
5275 }
5276
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005277 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5278 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005279 if(not defined $TypeInfo{$Version}{$ClassId}
5280 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5281 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005282 delete($SymbolInfo{$Version}{$InfoId});
5283 return;
5284 }
5285 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005286 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5287 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005288 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005289 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005290 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005291 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005292 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005293 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005294 }
5295 if($COMMON_LANGUAGE{$Version} eq "C++")
5296 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005297 # C++ or --headers-only mode
5298 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005299 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005300 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5301 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005302 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005303 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005304 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005305 if(my $Mangled = linkSymbol($InfoId)) {
5306 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005307 }
5308 }
5309 if($OStarget eq "windows")
5310 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005311 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005312 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005313 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005314 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005315 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005316 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005317 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005318 }
5319 }
5320 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005321 else
5322 { # not mangled in C
5323 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5324 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005325 if(not $CheckHeadersOnly
5326 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5327 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5328 {
5329 my $Incorrect = 0;
5330
5331 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5332 {
5333 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5334 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5335 { # mangled in the TU dump, but not mangled in the library
5336 $Incorrect = 1;
5337 }
5338 }
5339 else
5340 {
5341 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5342 { # all C++ functions are not mangled in the TU dump
5343 $Incorrect = 1;
5344 }
5345 }
5346 if($Incorrect)
5347 {
5348 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5349 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5350 }
5351 }
5352 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005353 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005354 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005355 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005356 return;
5357 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005358 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005359 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005360 { # identify virtual and pure virtual functions
5361 # NOTE: constructors cannot be virtual
5362 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5363 # in the TU dump, so taking it from the original symbol
5364 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5365 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5366 { # NOTE: D2 destructors are not present in a v-table
5367 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5368 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005369 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005370 if(isInline($InfoId)) {
5371 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005372 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005373 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005374 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5375 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005376 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5377 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005378 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005379 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005380 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005381 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005382 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005383 }
5384 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005385 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5386 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005387 if(not $ExtraDump)
5388 {
5389 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5390 { # non-target symbols
5391 delete($SymbolInfo{$Version}{$InfoId});
5392 return;
5393 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005394 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005395 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005396 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5397 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5398 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5399 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005400 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005401 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5402 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005403 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005404 return;
5405 }
5406 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005407 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005408 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005409 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005410 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005411 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005412 return;
5413 }
5414 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005415 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005416 }
5417 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005418 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5419 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5420 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005421 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005422 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5423 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005424 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005425 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005426 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005427 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005428 }
5429 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005430 if(getFuncLink($InfoId) eq "Static") {
5431 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005432 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005433 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5434 {
5435 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5436 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005437 if($Unmangled=~/\.\_\d/)
5438 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005439 delete($SymbolInfo{$Version}{$InfoId});
5440 return;
5441 }
5442 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005443 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005444
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005445 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5446 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005447 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005448 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5449 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005450 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005451
5452 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5453 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5454 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005455
5456 if($ExtraDump) {
5457 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5458 }
5459}
5460
5461sub guessHeader($)
5462{
5463 my $InfoId = $_[0];
5464 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5465 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5466 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5467 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5468 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5469 {
5470 if(get_filename($HPath) eq $Header)
5471 {
5472 my $HDir = get_filename(get_dirname($HPath));
5473 if($HDir ne "include"
5474 and $HDir=~/\A[a-z]+\Z/i) {
5475 return join_P($HDir, $Header);
5476 }
5477 }
5478 }
5479 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005480}
5481
5482sub isInline($)
5483{ # "body: undefined" in the tree
5484 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005485 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5486 {
5487 if($Info=~/ undefined /i) {
5488 return 0;
5489 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005490 }
5491 return 1;
5492}
5493
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005494sub hasThrow($)
5495{
5496 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5497 {
5498 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5499 return getTreeAttr_Unql($1, "unql");
5500 }
5501 }
5502 return 1;
5503}
5504
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005505sub getTypeId($)
5506{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005507 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5508 {
5509 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5510 return $1;
5511 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005512 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005513 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005514}
5515
5516sub setTypeMemb($$)
5517{
5518 my ($TypeId, $TypeAttr) = @_;
5519 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005520 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005521 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005522 if($TypeType eq "Enum")
5523 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005524 my $MInfoId = getTreeAttr_Csts($TypeId);
5525 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005526 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005527 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5528 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005529 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005530 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5531 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005532 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005533 }
5534 }
5535 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5536 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005537 my $MInfoId = getTreeAttr_Flds($TypeId);
5538 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005539 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005540 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5541 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005542 if(not $IType or $IType ne "field_decl")
5543 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005544
5545 if($IType eq "var_decl")
5546 { # static field
5547 $StaticFields = 1;
5548 }
5549
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005550 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005551 next;
5552 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005553 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005554 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005555 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005556 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005557 }
5558 if(not $StructMembName)
5559 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005560 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005561 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005562 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005563 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5564 if(isAnon($UnnamedTName))
5565 { # rename unnamed fields to unnamed0, unnamed1, ...
5566 $StructMembName = "unnamed".($UnnamedPos++);
5567 }
5568 }
5569 }
5570 if(not $StructMembName)
5571 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005572 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005573 next;
5574 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005575 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005576 if(defined $MissedTypedef{$Version}{$MembTypeId})
5577 {
5578 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5579 $MembTypeId = $AddedTid;
5580 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005581 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005582
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005583 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5584 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005585 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005586 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005587 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5588 }
5589 if($MInfo=~/spec:\s*mutable /)
5590 { # mutable fields
5591 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005592 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005593 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005594 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5595 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005596 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005597 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005598 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005599 }
5600 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005601 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005602 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5603 { # template
5604 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5605 }
5606 else {
5607 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5608 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005609 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005610
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005611 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005612 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005613 }
5614 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005615
5616 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005617}
5618
5619sub setFuncParams($)
5620{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005621 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005622 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005623
5624 my $FType = getFuncType($InfoId);
5625
5626 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005627 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005628 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5629 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005630 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005631 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005632 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5633 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005634 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005635 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5636 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005637 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005638 else
5639 { # skip
5640 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005641 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005642 # skip "this"-parameter
5643 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005644 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005645 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005646 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005647 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005648 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5649 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5650 if(not $ParamName)
5651 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005652 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005653 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005654 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5655 {
5656 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5657 $ParamTypeId = $AddedTid;
5658 }
5659 }
5660 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005661 if(not $PType or $PType eq "Unknown") {
5662 return 1;
5663 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005664 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005665 if(not $PTName) {
5666 return 1;
5667 }
5668 if($PTName eq "void") {
5669 last;
5670 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005671 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005672 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005673 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005674 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005675 $ParamInfoId = getNextElem($ParamInfoId);
5676 next;
5677 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005678 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005679
5680 if(my %Base = get_BaseType($ParamTypeId, $Version))
5681 {
5682 if(defined $Base{"Template"}) {
5683 return 1;
5684 }
5685 }
5686
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005687 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005688 if(my $Algn = getAlgn($ParamInfoId)) {
5689 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5690 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005691 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5692 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005693 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005694 }
5695 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005696 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005697 if($ParamName ne "this" or $FType ne "Method") {
5698 $PPos += 1;
5699 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005700 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005701 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005702 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005703 }
5704 return 0;
5705}
5706
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005707sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005708{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005709 my ($InfoId, $Vtt_Pos) = @_;
5710 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005711 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005712 my $FType = getFuncType($InfoId);
5713
5714 if($FType eq "Method")
5715 {
5716 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005717 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005718 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005719 if(not $ParamListElemId)
5720 { # foo(...)
5721 return 1;
5722 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005723 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005724 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005725 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005726 { # actual params: may differ from formal args
5727 # formal int*const
5728 # actual: int*
5729 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005730 {
5731 $Vtt_Pos=-1;
5732 $ParamListElemId = getNextElem($ParamListElemId);
5733 next;
5734 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005735 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5736 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005737 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005738 $HaveVoid = 1;
5739 last;
5740 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005741 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005742 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005743 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5744 {
5745 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5746 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5747 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005748 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005749 }
5750 }
5751 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5752 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005753 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005754 { # params
5755 if($OldId ne $ParamTypeId)
5756 {
5757 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5758 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5759
5760 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5761 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5762 }
5763 }
5764 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005765 }
5766 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005767 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005768 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005769 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5770 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005771 if($PurpType eq "nop_expr")
5772 { # func ( const char* arg = (const char*)(void*)0 )
5773 $PurpId = getTreeAttr_Op($PurpId);
5774 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005775 my $Val = getInitVal($PurpId, $ParamTypeId);
5776 if(defined $Val) {
5777 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5778 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005779 }
5780 }
5781 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005782 if($Pos!=0 or $FType ne "Method") {
5783 $PPos += 1;
5784 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005785 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005786 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005787 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005788}
5789
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005790sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005791{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005792 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5793 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005794 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5795 return $1;
5796 }
5797 }
5798 return "";
5799}
5800
5801sub getTreeAttr_Chain($)
5802{
5803 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5804 {
5805 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5806 return $1;
5807 }
5808 }
5809 return "";
5810}
5811
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005812sub getTreeAttr_Unql($)
5813{
5814 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5815 {
5816 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5817 return $1;
5818 }
5819 }
5820 return "";
5821}
5822
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005823sub getTreeAttr_Scpe($)
5824{
5825 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5826 {
5827 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5828 return $1;
5829 }
5830 }
5831 return "";
5832}
5833
5834sub getTreeAttr_Type($)
5835{
5836 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5837 {
5838 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5839 return $1;
5840 }
5841 }
5842 return "";
5843}
5844
5845sub getTreeAttr_Name($)
5846{
5847 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5848 {
5849 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5850 return $1;
5851 }
5852 }
5853 return "";
5854}
5855
5856sub getTreeAttr_Mngl($)
5857{
5858 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5859 {
5860 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5861 return $1;
5862 }
5863 }
5864 return "";
5865}
5866
5867sub getTreeAttr_Prms($)
5868{
5869 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5870 {
5871 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5872 return $1;
5873 }
5874 }
5875 return "";
5876}
5877
5878sub getTreeAttr_Fncs($)
5879{
5880 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5881 {
5882 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5883 return $1;
5884 }
5885 }
5886 return "";
5887}
5888
5889sub getTreeAttr_Csts($)
5890{
5891 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5892 {
5893 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5894 return $1;
5895 }
5896 }
5897 return "";
5898}
5899
5900sub getTreeAttr_Purp($)
5901{
5902 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5903 {
5904 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5905 return $1;
5906 }
5907 }
5908 return "";
5909}
5910
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005911sub getTreeAttr_Op($)
5912{
5913 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5914 {
5915 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5916 return $1;
5917 }
5918 }
5919 return "";
5920}
5921
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005922sub getTreeAttr_Valu($)
5923{
5924 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5925 {
5926 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5927 return $1;
5928 }
5929 }
5930 return "";
5931}
5932
5933sub getTreeAttr_Flds($)
5934{
5935 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5936 {
5937 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5938 return $1;
5939 }
5940 }
5941 return "";
5942}
5943
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005944sub getTreeAttr_Binf($)
5945{
5946 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5947 {
5948 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5949 return $1;
5950 }
5951 }
5952 return "";
5953}
5954
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005955sub getTreeAttr_Args($)
5956{
5957 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5958 {
5959 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005960 return $1;
5961 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005962 }
5963 return "";
5964}
5965
5966sub getTreeValue($)
5967{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005968 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5969 {
5970 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5971 return $1;
5972 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005973 }
5974 return "";
5975}
5976
5977sub getTreeAccess($)
5978{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005979 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005980 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005981 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5982 {
5983 my $Access = $1;
5984 if($Access eq "prot") {
5985 return "protected";
5986 }
5987 elsif($Access eq "priv") {
5988 return "private";
5989 }
5990 }
5991 elsif($Info=~/ protected /)
5992 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005993 return "protected";
5994 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005995 elsif($Info=~/ private /)
5996 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005997 return "private";
5998 }
5999 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006000 return "public";
6001}
6002
6003sub setFuncAccess($)
6004{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006005 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006006 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006007 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006008 }
6009 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006010 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006011 }
6012}
6013
6014sub setTypeAccess($$)
6015{
6016 my ($TypeId, $TypeAttr) = @_;
6017 my $Access = getTreeAccess($TypeId);
6018 if($Access eq "protected") {
6019 $TypeAttr->{"Protected"} = 1;
6020 }
6021 elsif($Access eq "private") {
6022 $TypeAttr->{"Private"} = 1;
6023 }
6024}
6025
6026sub setFuncKind($)
6027{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006028 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6029 {
6030 if($Info=~/pseudo tmpl/) {
6031 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
6032 }
6033 elsif($Info=~/ constructor /) {
6034 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
6035 }
6036 elsif($Info=~/ destructor /) {
6037 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
6038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006039 }
6040}
6041
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006042sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006043{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006044 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6045 {
6046 if($Info=~/spec[ ]*:[ ]*pure /) {
6047 return "PureVirt";
6048 }
6049 elsif($Info=~/spec[ ]*:[ ]*virt /) {
6050 return "Virt";
6051 }
6052 elsif($Info=~/ pure\s+virtual /)
6053 { # support for old GCC versions
6054 return "PureVirt";
6055 }
6056 elsif($Info=~/ virtual /)
6057 { # support for old GCC versions
6058 return "Virt";
6059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006060 }
6061 return "";
6062}
6063
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006064sub getFuncLink($)
6065{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006066 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6067 {
6068 if($Info=~/link[ ]*:[ ]*static /) {
6069 return "Static";
6070 }
6071 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006072 return $1;
6073 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006074 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006075 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006076}
6077
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006078sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006079{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006080 my ($Symbol, $LibVersion) = @_;
6081 return "" if(not $Symbol or not $LibVersion);
6082 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
6083 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006084 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006085 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
6086 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
6087 }
6088 }
6089 if($NS)
6090 {
6091 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6092 return $NS;
6093 }
6094 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006095 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006096 while($NS=~s/::[^:]+\Z//)
6097 {
6098 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6099 return $NS;
6100 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006101 }
6102 }
6103 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006104
6105 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006106}
6107
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006108sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006109{
6110 my ($TypeName, $LibVersion) = @_;
6111 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006112 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006113 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006114 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6115 return $NS;
6116 }
6117 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006118 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006119 while($NS=~s/::[^:]+\Z//)
6120 {
6121 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6122 return $NS;
6123 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006124 }
6125 }
6126 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006127 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006128}
6129
6130sub getNameSpace($)
6131{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006132 my $InfoId = $_[0];
6133 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006134 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006135 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006136 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006137 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006138 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006139 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6140 {
6141 my $NameSpace = getTreeStr($1);
6142 if($NameSpace eq "::")
6143 { # global namespace
6144 return "";
6145 }
6146 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6147 $NameSpace = $BaseNameSpace."::".$NameSpace;
6148 }
6149 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6150 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006151 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006152 else {
6153 return "";
6154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006155 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006156 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006157 { # inside data type
6158 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6159 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006160 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006161 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006162 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006163 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006164}
6165
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006166sub getEnumMembVal($)
6167{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006168 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006169 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006170 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6171 {
6172 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6173 {
6174 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6175 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6176 return getTreeValue($1);
6177 }
6178 else
6179 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6180 return getTreeValue($1);
6181 }
6182 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006183 }
6184 }
6185 return "";
6186}
6187
6188sub getSize($)
6189{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006190 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6191 {
6192 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6193 return getTreeValue($1);
6194 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006195 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006196 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006197}
6198
6199sub getAlgn($)
6200{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006201 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6202 {
6203 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6204 return $1;
6205 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006206 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006207 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006208}
6209
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006210sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006211{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006212 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6213 {
6214 if($Info=~/ bitfield /) {
6215 return getSize($_[0]);
6216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006217 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006218 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006219}
6220
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006221sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006222{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006223 if(my $Chan = getTreeAttr_Chan($_[0])) {
6224 return $Chan;
6225 }
6226 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6227 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006228 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006229 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006230}
6231
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006232sub registerHeader($$)
6233{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006234 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006235 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006236 return "";
6237 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006238 if(is_abs($Header) and not -f $Header)
6239 { # incorrect absolute path
6240 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006241 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006242 if(skipHeader($Header, $LibVersion))
6243 { # skip
6244 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006245 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006246 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6247 {
6248 detect_header_includes($Header_Path, $LibVersion);
6249
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006250 if(defined $Tolerance and $Tolerance=~/3/)
6251 { # 3 - skip headers that include non-Linux headers
6252 if($OSgroup ne "windows")
6253 {
6254 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6255 {
6256 if(specificHeader($Inc, "windows")) {
6257 return "";
6258 }
6259 }
6260 }
6261 }
6262
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006263 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6264 { # redirect
6265 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6266 or skipHeader($RHeader_Path, $LibVersion))
6267 { # skip
6268 return "";
6269 }
6270 $Header_Path = $RHeader_Path;
6271 }
6272 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6273 { # skip
6274 return "";
6275 }
6276
6277 if(my $HName = get_filename($Header_Path))
6278 { # register
6279 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6280 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6281 }
6282
6283 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6284 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006285 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006286 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006287 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006288 }
6289
6290 if($CheckHeadersOnly
6291 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6292 { # /usr/include/c++/4.6.1/...
6293 $STDCXX_TESTING = 1;
6294 }
6295
6296 return $Header_Path;
6297 }
6298 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006299}
6300
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006301sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006302{
6303 my ($Dir, $WithDeps, $LibVersion) = @_;
6304 $Dir=~s/[\/\\]+\Z//g;
6305 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006306 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006307
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006308 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006309 if($WithDeps)
6310 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006311 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6312 return;
6313 }
6314 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6315 $Mode = "DepsOnly";
6316 }
6317 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006318 else
6319 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006320 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6321 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6322 return;
6323 }
6324 }
6325 $Header_Dependency{$LibVersion}{$Dir} = 1;
6326 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6327 if($Mode eq "DepsOnly")
6328 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006329 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006330 $Header_Dependency{$LibVersion}{$Path} = 1;
6331 }
6332 return;
6333 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006334 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006335 {
6336 if($WithDeps)
6337 {
6338 my $SubDir = $Path;
6339 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6340 { # register all sub directories
6341 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6342 }
6343 }
6344 next if(is_not_header($Path));
6345 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006346 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006347 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006348 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6349 }
6350 }
6351 if(get_filename($Dir) eq "include")
6352 { # search for "lib/include/" directory
6353 my $LibDir = $Dir;
6354 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006355 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006356 }
6357 }
6358}
6359
6360sub parse_redirect($$$)
6361{
6362 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006363 my @Errors = ();
6364 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6365 push(@Errors, $1);
6366 }
6367 my $Redirect = "";
6368 foreach (@Errors)
6369 {
6370 s/\s{2,}/ /g;
6371 if(/(only|must\ include
6372 |update\ to\ include
6373 |replaced\ with
6374 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006375 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006376 {
6377 $Redirect = $2;
6378 last;
6379 }
6380 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6381 {
6382 $Redirect = $2;
6383 last;
6384 }
6385 elsif(/this\ header\ should\ not\ be\ used
6386 |programs\ should\ not\ directly\ include
6387 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6388 |is\ not\ supported\ API\ for\ general\ use
6389 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006390 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006391 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6392 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6393 }
6394 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006395 if($Redirect)
6396 {
6397 $Redirect=~s/\A<//g;
6398 $Redirect=~s/>\Z//g;
6399 }
6400 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006401}
6402
6403sub parse_includes($$)
6404{
6405 my ($Content, $Path) = @_;
6406 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006407 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006408 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006409 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006410 my $Method = substr($Header, 0, 1, "");
6411 substr($Header, length($Header)-1, 1, "");
6412 $Header = path_format($Header, $OSgroup);
6413 if($Method eq "\"" or is_abs($Header))
6414 {
6415 if(-e join_P(get_dirname($Path), $Header))
6416 { # relative path exists
6417 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006418 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006419 else
6420 { # include "..." that doesn't exist is equal to include <...>
6421 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006422 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006423 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006424 else {
6425 $Includes{$Header} = 1;
6426 }
6427 }
6428 if($ExtraInfo)
6429 {
6430 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6431 { # FT_FREETYPE_H
6432 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006433 }
6434 }
6435 return \%Includes;
6436}
6437
6438sub ignore_path($)
6439{
6440 my $Path = $_[0];
6441 if($Path=~/\~\Z/)
6442 {# skipping system backup files
6443 return 1;
6444 }
6445 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6446 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6447 return 1;
6448 }
6449 return 0;
6450}
6451
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006452sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006453{
6454 my ($ArrRef, $W) = @_;
6455 return if(length($W)<2);
6456 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6457}
6458
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006459sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006460{
6461 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006462
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006463 $H1=~s/\.[a-z]+\Z//ig;
6464 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006465
6466 my $Hname1 = get_filename($H1);
6467 my $Hname2 = get_filename($H2);
6468 my $HDir1 = get_dirname($H1);
6469 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006470 my $Dirname1 = get_filename($HDir1);
6471 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006472
6473 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6474 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6475
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006476 if($_[0] eq $_[1]
6477 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006478 return 0;
6479 }
6480 elsif($H1=~/\A\Q$H2\E/) {
6481 return 1;
6482 }
6483 elsif($H2=~/\A\Q$H1\E/) {
6484 return -1;
6485 }
6486 elsif($HDir1=~/\Q$Hname1\E/i
6487 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006488 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006489 return -1;
6490 }
6491 elsif($HDir2=~/\Q$Hname2\E/i
6492 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006493 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006494 return 1;
6495 }
6496 elsif($Hname1=~/\Q$Dirname1\E/i
6497 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006498 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006499 return -1;
6500 }
6501 elsif($Hname2=~/\Q$Dirname2\E/i
6502 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006503 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006504 return 1;
6505 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006506 elsif($Hname1=~/(config|lib|util)/i
6507 and $Hname2!~/(config|lib|util)/i)
6508 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006509 return -1;
6510 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006511 elsif($Hname2=~/(config|lib|util)/i
6512 and $Hname1!~/(config|lib|util)/i)
6513 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006514 return 1;
6515 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006516 else
6517 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006518 my $R1 = checkRelevance($H1);
6519 my $R2 = checkRelevance($H2);
6520 if($R1 and not $R2)
6521 { # libebook/e-book.h
6522 return -1;
6523 }
6524 elsif($R2 and not $R1)
6525 { # libebook/e-book.h
6526 return 1;
6527 }
6528 else
6529 {
6530 return (lc($H1) cmp lc($H2));
6531 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006532 }
6533}
6534
6535sub searchForHeaders($)
6536{
6537 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006538
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006539 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006540 registerGccHeaders();
6541
6542 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6543 { # c++ standard include paths
6544 registerCppHeaders();
6545 }
6546
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006547 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006548 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6549 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006550 {
6551 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006552 if($SystemRoot)
6553 {
6554 if(is_abs($Path)) {
6555 $Path = $SystemRoot.$Path;
6556 }
6557 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006558 if(not -e $Path) {
6559 exitStatus("Access_Error", "can't access \'$Path\'");
6560 }
6561 elsif(-f $Path) {
6562 exitStatus("Access_Error", "\'$Path\' - not a directory");
6563 }
6564 elsif(-d $Path)
6565 {
6566 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006567 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006568 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6569 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006570 }
6571 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006572 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006573 }
6574 }
6575 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006576 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006577 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6578 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006579
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006580 # registering directories
6581 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6582 {
6583 next if(not -e $Path);
6584 $Path = get_abs_path($Path);
6585 $Path = path_format($Path, $OSgroup);
6586 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006587 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006588 }
6589 elsif(-f $Path)
6590 {
6591 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006592 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006593 and not $LocalIncludes{$Dir})
6594 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006595 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006596 # if(my $OutDir = get_dirname($Dir))
6597 # { # registering the outer directory
6598 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6599 # and not $LocalIncludes{$OutDir}) {
6600 # registerDir($OutDir, 0, $LibVersion);
6601 # }
6602 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006603 }
6604 }
6605 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006606
6607 # clean memory
6608 %RegisteredDirs = ();
6609
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006610 # registering headers
6611 my $Position = 0;
6612 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6613 {
6614 if(is_abs($Dest) and not -e $Dest) {
6615 exitStatus("Access_Error", "can't access \'$Dest\'");
6616 }
6617 $Dest = path_format($Dest, $OSgroup);
6618 if(is_header($Dest, 1, $LibVersion))
6619 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006620 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006621 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6622 }
6623 }
6624 elsif(-d $Dest)
6625 {
6626 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006627 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006628 {
6629 next if(ignore_path($Path));
6630 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006631 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006632 push(@Registered, $HPath);
6633 }
6634 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006635 @Registered = sort {sortHeaders($a, $b)} @Registered;
6636 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006637 foreach my $Path (@Registered) {
6638 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6639 }
6640 }
6641 else {
6642 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6643 }
6644 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006645
6646 if(defined $Tolerance and $Tolerance=~/4/)
6647 { # 4 - skip headers included by others
6648 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6649 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006650 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006651 delete($Registered_Headers{$LibVersion}{$Path});
6652 }
6653 }
6654 }
6655
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006656 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6657 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006658 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006659 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006660 if(is_abs($Header) and not -f $Header) {
6661 exitStatus("Access_Error", "can't access file \'$Header\'");
6662 }
6663 $Header = path_format($Header, $OSgroup);
6664 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6665 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006666 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006667 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006668 }
6669 else {
6670 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6671 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006672 }
6673 }
6674 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6675 { # set relative paths (for duplicates)
6676 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6677 { # search for duplicates
6678 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6679 my $Prefix = get_dirname($FirstPath);
6680 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6681 { # detect a shortest distinguishing prefix
6682 my $NewPrefix = $1;
6683 my %Identity = ();
6684 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6685 {
6686 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6687 $Identity{$Path} = $1;
6688 }
6689 }
6690 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6691 { # all names are differend with current prefix
6692 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6693 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6694 }
6695 last;
6696 }
6697 $Prefix = $NewPrefix; # increase prefix
6698 }
6699 }
6700 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006701
6702 # clean memory
6703 %HeaderName_Paths = ();
6704
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006705 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6706 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006707 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006708 my ($Pos, $PairPos) = (-1, -1);
6709 my ($Path, $PairPath) = ();
6710 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6711 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6712 foreach my $Header_Path (@Paths)
6713 {
6714 if(get_filename($Header_Path) eq $PairName)
6715 {
6716 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6717 $PairPath = $Header_Path;
6718 }
6719 if(get_filename($Header_Path) eq $HeaderName)
6720 {
6721 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6722 $Path = $Header_Path;
6723 }
6724 }
6725 if($PairPos!=-1 and $Pos!=-1
6726 and int($PairPos)<int($Pos))
6727 {
6728 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6729 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6730 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6731 }
6732 }
6733 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6734 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6735 }
6736}
6737
6738sub detect_real_includes($$)
6739{
6740 my ($AbsPath, $LibVersion) = @_;
6741 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6742 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6743 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6744 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6745 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006746 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6747
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006748 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6749 return () if(not $Path);
6750 open(PREPROC, $Path);
6751 while(<PREPROC>)
6752 {
6753 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6754 {
6755 my $Include = path_format($1, $OSgroup);
6756 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6757 next;
6758 }
6759 if($Include eq $AbsPath) {
6760 next;
6761 }
6762 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6763 }
6764 }
6765 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006766 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6767}
6768
6769sub detect_header_includes($$)
6770{
6771 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006772 return if(not $LibVersion or not $Path);
6773 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6774 return;
6775 }
6776 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6777
6778 if(not -e $Path) {
6779 return;
6780 }
6781
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006782 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006783 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6784 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006785 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006786 {
6787 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006788 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006789 }
6790 if($RedirectPath ne $Path) {
6791 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6792 }
6793 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006794 else
6795 { # can't find
6796 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6797 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006798 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006799 if(my $Inc = parse_includes($Content, $Path))
6800 {
6801 foreach my $Include (keys(%{$Inc}))
6802 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006803 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006804
6805 if(defined $Tolerance and $Tolerance=~/4/)
6806 {
6807 if(my $HPath = identifyHeader($Include, $LibVersion))
6808 {
6809 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6810 }
6811 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006813 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006814}
6815
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006816sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006817{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006818 my $Path = $_[0];
6819 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006820 if($OStarget eq "symbian")
6821 {
6822 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6823 { # epoc32/include/libc/{stdio, ...}.h
6824 return 1;
6825 }
6826 }
6827 else
6828 {
6829 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6830 { # /usr/include/{stdio, ...}.h
6831 return 1;
6832 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006833 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006834 return 0;
6835}
6836
6837sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006838{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006839 my $Dir = $_[0];
6840 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006841 if($OStarget eq "symbian")
6842 {
6843 if(get_filename($OutDir) eq "libc"
6844 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6845 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6846 return 1;
6847 }
6848 }
6849 else
6850 { # linux
6851 if($OutDir eq "/usr/include"
6852 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6853 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6854 return 1;
6855 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006856 }
6857 return 0;
6858}
6859
6860sub detect_recursive_includes($$)
6861{
6862 my ($AbsPath, $LibVersion) = @_;
6863 return () if(not $AbsPath);
6864 if(isCyclical(\@RecurInclude, $AbsPath)) {
6865 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6866 }
6867 my ($AbsDir, $Name) = separate_path($AbsPath);
6868 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006869 { # system GLIBC internals
6870 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006871 }
6872 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6873 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6874 }
6875 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006876
6877 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6878 { # skip /usr/include/c++/*/ headers
6879 return () if(not $ExtraInfo);
6880 }
6881
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006882 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006883 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006884 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006885 { # check "real" (non-"model") include paths
6886 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6887 pop(@RecurInclude);
6888 return @Paths;
6889 }
6890 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6891 detect_header_includes($AbsPath, $LibVersion);
6892 }
6893 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6894 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006895 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006896 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006897 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006898 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006899 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006900 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006901 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006902 }
6903 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006904 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006905 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006906 { # search for the nearest header
6907 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006908 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006909 if(-f $Candidate) {
6910 $HPath = $Candidate;
6911 }
6912 }
6913 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006914 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006915 }
6916 next if(not $HPath);
6917 if($HPath eq $AbsPath) {
6918 next;
6919 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006920
6921 if($Debug)
6922 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006923# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6924# {
6925# print STDERR "$AbsPath -> $HPath\n";
6926# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006927 }
6928
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006929 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6930 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006931 { # only include <...>, skip include "..." prefixes
6932 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6933 }
6934 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6935 {
6936 if($IncPath eq $AbsPath) {
6937 next;
6938 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006939 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6940 if($RIncType==-1)
6941 { # include "..."
6942 $RIncType = $IncType;
6943 }
6944 elsif($RIncType==2)
6945 {
6946 if($IncType!=-1) {
6947 $RIncType = $IncType;
6948 }
6949 }
6950 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006951 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6952 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6953 }
6954 }
6955 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6956 {
6957 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6958 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6959 { # distinguish math.h from glibc and math.h from the tested library
6960 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6961 last;
6962 }
6963 }
6964 }
6965 pop(@RecurInclude);
6966 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6967}
6968
6969sub find_in_framework($$$)
6970{
6971 my ($Header, $Framework, $LibVersion) = @_;
6972 return "" if(not $Header or not $Framework or not $LibVersion);
6973 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6974 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6975 }
6976 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6977 {
6978 if(get_filename($Dependency) eq $Framework
6979 and -f get_dirname($Dependency)."/".$Header) {
6980 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6981 }
6982 }
6983 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6984}
6985
6986sub find_in_defaults($)
6987{
6988 my $Header = $_[0];
6989 return "" if(not $Header);
6990 if(defined $Cache{"find_in_defaults"}{$Header}) {
6991 return $Cache{"find_in_defaults"}{$Header};
6992 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006993 foreach my $Dir (@DefaultIncPaths,
6994 @DefaultGccPaths,
6995 @DefaultCppPaths,
6996 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006997 {
6998 next if(not $Dir);
6999 if(-f $Dir."/".$Header) {
7000 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
7001 }
7002 }
7003 return ($Cache{"find_in_defaults"}{$Header}="");
7004}
7005
7006sub cmp_paths($$)
7007{
7008 my ($Path1, $Path2) = @_;
7009 my @Parts1 = split(/[\/\\]/, $Path1);
7010 my @Parts2 = split(/[\/\\]/, $Path2);
7011 foreach my $Num (0 .. $#Parts1)
7012 {
7013 my $Part1 = $Parts1[$Num];
7014 my $Part2 = $Parts2[$Num];
7015 if($GlibcDir{$Part1}
7016 and not $GlibcDir{$Part2}) {
7017 return 1;
7018 }
7019 elsif($GlibcDir{$Part2}
7020 and not $GlibcDir{$Part1}) {
7021 return -1;
7022 }
7023 elsif($Part1=~/glib/
7024 and $Part2!~/glib/) {
7025 return 1;
7026 }
7027 elsif($Part1!~/glib/
7028 and $Part2=~/glib/) {
7029 return -1;
7030 }
7031 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
7032 return $CmpRes;
7033 }
7034 }
7035 return 0;
7036}
7037
7038sub checkRelevance($)
7039{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007040 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007041 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007042
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007043 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007044 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007045 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007046
7047 my $Name = lc(get_filename($Path));
7048 my $Dir = lc(get_dirname($Path));
7049
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007050 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007051
7052 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007053 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007054 my $Len = length($Token);
7055 next if($Len<=1);
7056 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
7057 { # include/evolution-data-server-1.4/libebook/e-book.h
7058 return 1;
7059 }
7060 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007061 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007062 return 1;
7063 }
7064 }
7065 return 0;
7066}
7067
7068sub checkFamily(@)
7069{
7070 my @Paths = @_;
7071 return 1 if($#Paths<=0);
7072 my %Prefix = ();
7073 foreach my $Path (@Paths)
7074 {
7075 if($SystemRoot) {
7076 $Path = cut_path_prefix($Path, $SystemRoot);
7077 }
7078 if(my $Dir = get_dirname($Path))
7079 {
7080 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
7081 $Prefix{$Dir} += 1;
7082 $Prefix{get_dirname($Dir)} += 1;
7083 }
7084 }
7085 foreach (sort keys(%Prefix))
7086 {
7087 if(get_depth($_)>=3
7088 and $Prefix{$_}==$#Paths+1) {
7089 return 1;
7090 }
7091 }
7092 return 0;
7093}
7094
7095sub isAcceptable($$$)
7096{
7097 my ($Header, $Candidate, $LibVersion) = @_;
7098 my $HName = get_filename($Header);
7099 if(get_dirname($Header))
7100 { # with prefix
7101 return 1;
7102 }
7103 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
7104 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
7105 return 1;
7106 }
7107 if(checkRelevance($Candidate))
7108 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
7109 return 1;
7110 }
7111 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
7112 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
7113 # /usr/include/qt4/Qt/qsslconfiguration.h
7114 return 1;
7115 }
7116 if($OStarget eq "symbian")
7117 {
7118 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
7119 return 1;
7120 }
7121 }
7122 return 0;
7123}
7124
7125sub isRelevant($$$)
7126{ # disallow to search for "abstract" headers in too deep directories
7127 my ($Header, $Candidate, $LibVersion) = @_;
7128 my $HName = get_filename($Header);
7129 if($OStarget eq "symbian")
7130 {
7131 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7132 return 0;
7133 }
7134 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007135 if($OStarget ne "bsd")
7136 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007137 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7138 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7139 return 0;
7140 }
7141 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007142 if($OStarget ne "windows")
7143 {
7144 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7145 { # skip /usr/include/wine/msvcrt
7146 return 0;
7147 }
7148 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007149 if(not get_dirname($Header)
7150 and $Candidate=~/[\/\\]wx[\/\\]/)
7151 { # do NOT search in system /wx/ directory
7152 # for headers without a prefix: sstream.h
7153 return 0;
7154 }
7155 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7156 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7157 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7158 return 0;
7159 }
7160 if($Candidate=~/[\/\\]asm-/
7161 and (my $Arch = getArch($LibVersion)) ne "unknown")
7162 { # arch-specific header files
7163 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7164 {# skip ../asm-arm/ if using x86 architecture
7165 return 0;
7166 }
7167 }
7168 my @Candidates = getSystemHeaders($HName, $LibVersion);
7169 if($#Candidates==1)
7170 { # unique header
7171 return 1;
7172 }
7173 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7174 if($#SCandidates==1)
7175 { # unique name
7176 return 1;
7177 }
7178 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7179 if(get_depth($Candidate)-$SystemDepth>=5)
7180 { # abstract headers in too deep directories
7181 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7182 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7183 return 0;
7184 }
7185 }
7186 if($Header eq "parser.h"
7187 and $Candidate!~/\/libxml2\//)
7188 { # select parser.h from xml2 library
7189 return 0;
7190 }
7191 if(not get_dirname($Header)
7192 and keys(%{$SystemHeaders{$HName}})>=3)
7193 { # many headers with the same name
7194 # like thread.h included without a prefix
7195 if(not checkFamily(@Candidates)) {
7196 return 0;
7197 }
7198 }
7199 return 1;
7200}
7201
7202sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007203{ # cache function
7204 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7205 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7206 }
7207 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7208}
7209
7210sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007211{
7212 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007213 if(-f $Header) {
7214 return $Header;
7215 }
7216 if(is_abs($Header) and not -f $Header)
7217 { # incorrect absolute path
7218 return "";
7219 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007220 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007221 { # too abstract configuration headers
7222 return "";
7223 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007224 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007225 if($OSgroup ne "windows")
7226 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007227 if(defined $WinHeaders{lc($HName)}
7228 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007229 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007230 return "";
7231 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007232 }
7233 if($OSgroup ne "macos")
7234 {
7235 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007236 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007237 return "";
7238 }
7239 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007240
7241 if(defined $ObsoleteHeaders{$HName})
7242 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007243 return "";
7244 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007245 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7246 {
7247 if(defined $AlienHeaders{$HName}
7248 or defined $AlienHeaders{$Header})
7249 { # alien headers from other systems
7250 return "";
7251 }
7252 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007253
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007254 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007255 { # search in default paths
7256 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007257 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007258 }
7259 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007260 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007261 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007262 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007263 }
7264 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7265 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7266 {
7267 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007268 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007269 }
7270 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007271 # error
7272 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007273}
7274
7275sub getSystemHeaders($$)
7276{
7277 my ($Header, $LibVersion) = @_;
7278 my @Candidates = ();
7279 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7280 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007281 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007282 next;
7283 }
7284 push(@Candidates, $Candidate);
7285 }
7286 return @Candidates;
7287}
7288
7289sub cut_path_prefix($$)
7290{
7291 my ($Path, $Prefix) = @_;
7292 return $Path if(not $Prefix);
7293 $Prefix=~s/[\/\\]+\Z//;
7294 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7295 return $Path;
7296}
7297
7298sub is_default_include_dir($)
7299{
7300 my $Dir = $_[0];
7301 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007302 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007303}
7304
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007305sub identifyHeader($$)
7306{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007307 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007308 if(not $Header) {
7309 return "";
7310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007311 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007312 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7313 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007314 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007315 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007316}
7317
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007318sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007319{ # search for header by absolute path, relative path or name
7320 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007321 if(-f $Header)
7322 { # it's relative or absolute path
7323 return get_abs_path($Header);
7324 }
7325 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7326 and my $HeaderDir = find_in_defaults($Header))
7327 { # search for libc headers in the /usr/include
7328 # for non-libc target library before searching
7329 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007330 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007331 }
7332 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7333 { # search in the target library paths
7334 return $Path;
7335 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007336 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007337 { # search in the internal GCC include paths
7338 return $DefaultGccHeader{$Header};
7339 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007340 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007341 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007342 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007343 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007344 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007345 { # search in the default G++ include paths
7346 return $DefaultCppHeader{$Header};
7347 }
7348 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7349 { # search everywhere in the system
7350 return $AnyPath;
7351 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007352 elsif($OSgroup eq "macos")
7353 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7354 if(my $Dir = get_dirname($Header))
7355 {
7356 my $RelPath = "Headers\/".get_filename($Header);
7357 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007358 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007359 }
7360 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007361 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007362 # cannot find anything
7363 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007364}
7365
7366sub getLocation($)
7367{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007368 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7369 {
7370 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007371 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007372 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007373 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007374 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007375}
7376
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007377sub getNameByInfo($)
7378{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007379 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007380 {
7381 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7382 {
7383 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7384 {
7385 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7386 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007387 my $Str = $1;
7388 if($CppMode{$Version}
7389 and $Str=~/\Ac99_(.+)\Z/)
7390 {
7391 if($CppKeywords_A{$1}) {
7392 $Str=$1;
7393 }
7394 }
7395 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007396 }
7397 }
7398 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007399 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007400 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007401}
7402
7403sub getTreeStr($)
7404{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007405 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007406 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007407 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7408 {
7409 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007410 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007411 and $Str=~/\Ac99_(.+)\Z/)
7412 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007413 if($CppKeywords_A{$1}) {
7414 $Str=$1;
7415 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007416 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007417 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007418 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007419 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007420 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007421}
7422
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007423sub getFuncShortName($)
7424{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007425 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007426 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007427 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007428 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007429 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007430 {
7431 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7432 {
7433 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7434 return "operator ".$RName;
7435 }
7436 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007437 }
7438 else
7439 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007440 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7441 {
7442 if(my $Ind = $Operator_Indication{$1}) {
7443 return "operator".$Ind;
7444 }
7445 elsif(not $UnknownOperator{$1})
7446 {
7447 printMsg("WARNING", "unknown operator $1");
7448 $UnknownOperator{$1} = 1;
7449 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007450 }
7451 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007452 }
7453 else
7454 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007455 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7456 return getTreeStr($1);
7457 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007458 }
7459 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007460 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007461}
7462
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007463sub getFuncReturn($)
7464{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007465 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7466 {
7467 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7468 {
7469 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7470 return $1;
7471 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007472 }
7473 }
7474 return "";
7475}
7476
7477sub getFuncOrig($)
7478{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007479 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7480 {
7481 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7482 return $1;
7483 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007484 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007485 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007486}
7487
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007488sub unmangleArray(@)
7489{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007490 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007491 { # MSVC mangling
7492 my $UndNameCmd = get_CmdPath("undname");
7493 if(not $UndNameCmd) {
7494 exitStatus("Not_Found", "can't find \"undname\"");
7495 }
7496 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007497 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007498 }
7499 else
7500 { # GCC mangling
7501 my $CppFiltCmd = get_CmdPath("c++filt");
7502 if(not $CppFiltCmd) {
7503 exitStatus("Not_Found", "can't find c++filt in PATH");
7504 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007505 if(not defined $CPPFILT_SUPPORT_FILE)
7506 {
7507 my $Info = `$CppFiltCmd -h 2>&1`;
7508 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7509 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007510 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007511 if($CPPFILT_SUPPORT_FILE)
7512 { # new versions of c++filt can take a file
7513 if($#_>$MAX_CPPFILT_FILE_SIZE)
7514 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7515 # this is fixed in the oncoming version of Binutils
7516 my @Half = splice(@_, 0, ($#_+1)/2);
7517 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007518 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007519 else
7520 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007521 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7522 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7523 if($?==139)
7524 { # segmentation fault
7525 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7526 }
7527 return split(/\n/, $Res);
7528 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007529 }
7530 else
7531 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007532 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7533 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007534 my @Half = splice(@_, 0, ($#_+1)/2);
7535 return (unmangleArray(@Half), unmangleArray(@_))
7536 }
7537 else
7538 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007539 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007540 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7541 if($?==139)
7542 { # segmentation fault
7543 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7544 }
7545 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007546 }
7547 }
7548 }
7549}
7550
7551sub get_SignatureNoInfo($$)
7552{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007553 my ($Symbol, $LibVersion) = @_;
7554 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
7555 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007556 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007557 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007558 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007559 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007560 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04007561 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007562 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
7563 $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;
7564 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007565 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007566 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007567 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007568 $Signature .= " [data]";
7569 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007570 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007571 $Signature .= " (...)";
7572 }
7573 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007574 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007575 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04007576 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007577 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
7578 }
7579 if($SymbolVersion) {
7580 $Signature .= $VersionSpec.$SymbolVersion;
7581 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007582 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007583}
7584
7585sub get_ChargeLevel($$)
7586{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007587 my ($Symbol, $LibVersion) = @_;
7588 return "" if($Symbol!~/\A(_Z|\?)/);
7589 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7590 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007591 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007592 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007593 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007594 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007595 return "[in-charge]";
7596 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007597 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007598 return "[not-in-charge]";
7599 }
7600 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007601 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007602 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007603 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007604 return "[in-charge]";
7605 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007606 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007607 return "[not-in-charge]";
7608 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007609 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007610 return "[in-charge-deleting]";
7611 }
7612 }
7613 }
7614 else
7615 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007616 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007617 return "[in-charge]";
7618 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007619 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007620 return "[not-in-charge]";
7621 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007622 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007623 return "[in-charge]";
7624 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007625 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007626 return "[not-in-charge]";
7627 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007628 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007629 return "[in-charge-deleting]";
7630 }
7631 }
7632 return "";
7633}
7634
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007635sub get_Signature_M($$)
7636{
7637 my ($Symbol, $LibVersion) = @_;
7638 my $Signature_M = $tr_name{$Symbol};
7639 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7640 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007641 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007642 }
7643 return $Signature_M;
7644}
7645
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007646sub get_Signature($$)
7647{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007648 my ($Symbol, $LibVersion) = @_;
7649 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7650 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007651 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007652 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
7653 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007654 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007655 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007656 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007657 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007658 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7659 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007660 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007661 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7662 {
7663 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7664 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7665 $Signature .= "~";
7666 }
7667 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007668 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007669 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007670 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007671 }
7672 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007673 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007674 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007675 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7676 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007677 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007678 else
7679 {
7680 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007681 }
7682 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007683 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007684 {
7685 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007686 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007687 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007688 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007689 if(not $ParamTypeName) {
7690 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7691 }
7692 foreach my $Typedef (keys(%ChangedTypedef))
7693 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007694 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7695 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7696 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007697 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007698 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7699 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007700 if($ParamName eq "this"
7701 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007702 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007703 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007704 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007705 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007706 }
7707 else {
7708 push(@ParamArray, $ParamTypeName);
7709 }
7710 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007711 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7712 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007713 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007714 }
7715 else
7716 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007717 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007718 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007719 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007720 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007721 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007722 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7723 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007724 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007725 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007726 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7727 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007728 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007729 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007730 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7731 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007732 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007733 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007734 }
7735 }
7736 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007737 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007738 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007739 }
7740 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007741 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007742 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007743 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007744}
7745
7746sub create_member_decl($$)
7747{
7748 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007749 if($TName=~/\([\*]+\)/)
7750 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007751 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7752 return $TName;
7753 }
7754 else
7755 {
7756 my @ArraySizes = ();
7757 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7758 push(@ArraySizes, $1);
7759 }
7760 return $TName." ".$Member.join("", @ArraySizes);
7761 }
7762}
7763
7764sub getFuncType($)
7765{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007766 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7767 {
7768 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7769 {
7770 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7771 {
7772 if($Type eq "method_type") {
7773 return "Method";
7774 }
7775 elsif($Type eq "function_type") {
7776 return "Function";
7777 }
7778 else {
7779 return "Other";
7780 }
7781 }
7782 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007783 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007784 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007785}
7786
7787sub getFuncTypeId($)
7788{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007789 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7790 {
7791 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7792 return $1;
7793 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007794 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007795 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007796}
7797
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007798sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007799{ # "._N" or "$_N" in older GCC versions
7800 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007801}
7802
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007803sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007804{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007805 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7806 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007807 }
7808
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007809 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007810
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007811 if($_[1] ne "S")
7812 {
7813 $N=~s/\A[ ]+//g;
7814 $N=~s/[ ]+\Z//g;
7815 $N=~s/[ ]{2,}/ /g;
7816 }
7817
7818 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007819
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007820 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007821
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007822 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7823 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007824
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007825 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007826
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007827 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007828
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007829 if($_[1] eq "S")
7830 {
7831 if(index($N, "operator")!=-1) {
7832 $N=~s/\b(operator[ ]*)> >/$1>>/;
7833 }
7834 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007835
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007836 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007837}
7838
7839sub get_HeaderDeps($$)
7840{
7841 my ($AbsPath, $LibVersion) = @_;
7842 return () if(not $AbsPath or not $LibVersion);
7843 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7844 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7845 }
7846 my %IncDir = ();
7847 detect_recursive_includes($AbsPath, $LibVersion);
7848 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7849 {
7850 next if(not $HeaderPath);
7851 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7852 my $Dir = get_dirname($HeaderPath);
7853 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7854 {
7855 my $Dep = $Dir;
7856 if($Prefix)
7857 {
7858 if($OSgroup eq "windows")
7859 { # case insensitive seach on windows
7860 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7861 next;
7862 }
7863 }
7864 elsif($OSgroup eq "macos")
7865 { # seach in frameworks
7866 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7867 {
7868 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7869 {# frameworks
7870 my ($HFramework, $HName) = ($1, $2);
7871 $Dep = $HFramework;
7872 }
7873 else
7874 {# mismatch
7875 next;
7876 }
7877 }
7878 }
7879 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7880 { # Linux, FreeBSD
7881 next;
7882 }
7883 }
7884 if(not $Dep)
7885 { # nothing to include
7886 next;
7887 }
7888 if(is_default_include_dir($Dep))
7889 { # included by the compiler
7890 next;
7891 }
7892 if(get_depth($Dep)==1)
7893 { # too short
7894 next;
7895 }
7896 if(isLibcDir($Dep))
7897 { # do NOT include /usr/include/{sys,bits}
7898 next;
7899 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007900 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007901 }
7902 }
7903 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7904 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7905}
7906
7907sub sortIncPaths($$)
7908{
7909 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007910 if(not $ArrRef or $#{$ArrRef}<0) {
7911 return $ArrRef;
7912 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007913 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7914 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007915 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007916 return $ArrRef;
7917}
7918
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007919sub sortDeps($$$)
7920{
7921 if($Header_Dependency{$_[2]}{$_[0]}
7922 and not $Header_Dependency{$_[2]}{$_[1]}) {
7923 return 1;
7924 }
7925 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7926 and $Header_Dependency{$_[2]}{$_[1]}) {
7927 return -1;
7928 }
7929 return 0;
7930}
7931
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007932sub join_P($$)
7933{
7934 my $S = "/";
7935 if($OSgroup eq "windows") {
7936 $S = "\\";
7937 }
7938 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007939}
7940
7941sub get_namespace_additions($)
7942{
7943 my $NameSpaces = $_[0];
7944 my ($Additions, $AddNameSpaceId) = ("", 1);
7945 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7946 {
7947 next if($SkipNameSpaces{$Version}{$NS});
7948 next if(not $NS or $NameSpaces->{$NS}==-1);
7949 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7950 next if($NS=~/\A__/i);
7951 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007952 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007953 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7954 my @NS_Parts = split(/::/, $NS);
7955 next if($#NS_Parts==-1);
7956 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7957 foreach my $NS_Part (@NS_Parts)
7958 {
7959 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7960 $TypeDecl_Suffix .= "}";
7961 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007962 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007963 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7964 $Additions.=" $TypeDecl\n $FuncDecl\n";
7965 $AddNameSpaceId+=1;
7966 }
7967 return $Additions;
7968}
7969
7970sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007971{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007972 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007973 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007974 if($Fmt eq "windows")
7975 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007976 $Path=~s/\//\\/g;
7977 $Path=lc($Path);
7978 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007979 else
7980 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007981 $Path=~s/\\/\//g;
7982 }
7983 return $Path;
7984}
7985
7986sub inc_opt($$)
7987{
7988 my ($Path, $Style) = @_;
7989 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007990 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007991 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007992 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007993 return "-I\"".path_format($Path, "unix")."\"";
7994 }
7995 elsif($OSgroup eq "macos"
7996 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007997 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007998 return "-F".esc(get_dirname($Path));
7999 }
8000 else {
8001 return "-I".esc($Path);
8002 }
8003 }
8004 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008005 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008006 }
8007 return "";
8008}
8009
8010sub platformSpecs($)
8011{
8012 my $LibVersion = $_[0];
8013 my $Arch = getArch($LibVersion);
8014 if($OStarget eq "symbian")
8015 { # options for GCCE compiler
8016 my %Symbian_Opts = map {$_=>1} (
8017 "-D__GCCE__",
8018 "-DUNICODE",
8019 "-fexceptions",
8020 "-D__SYMBIAN32__",
8021 "-D__MARM_INTERWORK__",
8022 "-D_UNICODE",
8023 "-D__S60_50__",
8024 "-D__S60_3X__",
8025 "-D__SERIES60_3X__",
8026 "-D__EPOC32__",
8027 "-D__MARM__",
8028 "-D__EABI__",
8029 "-D__MARM_ARMV5__",
8030 "-D__SUPPORT_CPP_EXCEPTIONS__",
8031 "-march=armv5t",
8032 "-mapcs",
8033 "-mthumb-interwork",
8034 "-DEKA2",
8035 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
8036 );
8037 return join(" ", keys(%Symbian_Opts));
8038 }
8039 elsif($OSgroup eq "windows"
8040 and get_dumpmachine($GCC_PATH)=~/mingw/i)
8041 { # add options to MinGW compiler
8042 # to simulate the MSVC compiler
8043 my %MinGW_Opts = map {$_=>1} (
8044 "-D_WIN32",
8045 "-D_STDCALL_SUPPORTED",
8046 "-D__int64=\"long long\"",
8047 "-D__int32=int",
8048 "-D__int16=short",
8049 "-D__int8=char",
8050 "-D__possibly_notnullterminated=\" \"",
8051 "-D__nullterminated=\" \"",
8052 "-D__nullnullterminated=\" \"",
8053 "-D__w64=\" \"",
8054 "-D__ptr32=\" \"",
8055 "-D__ptr64=\" \"",
8056 "-D__forceinline=inline",
8057 "-D__inline=inline",
8058 "-D__uuidof(x)=IID()",
8059 "-D__try=",
8060 "-D__except(x)=",
8061 "-D__declspec(x)=__attribute__((x))",
8062 "-D__pragma(x)=",
8063 "-D_inline=inline",
8064 "-D__forceinline=__inline",
8065 "-D__stdcall=__attribute__((__stdcall__))",
8066 "-D__cdecl=__attribute__((__cdecl__))",
8067 "-D__fastcall=__attribute__((__fastcall__))",
8068 "-D__thiscall=__attribute__((__thiscall__))",
8069 "-D_stdcall=__attribute__((__stdcall__))",
8070 "-D_cdecl=__attribute__((__cdecl__))",
8071 "-D_fastcall=__attribute__((__fastcall__))",
8072 "-D_thiscall=__attribute__((__thiscall__))",
8073 "-DSHSTDAPI_(x)=x",
8074 "-D_MSC_EXTENSIONS",
8075 "-DSECURITY_WIN32",
8076 "-D_MSC_VER=1500",
8077 "-D_USE_DECLSPECS_FOR_SAL",
8078 "-D__noop=\" \"",
8079 "-DDECLSPEC_DEPRECATED=\" \"",
8080 "-D__builtin_alignof(x)=__alignof__(x)",
8081 "-DSORTPP_PASS");
8082 if($Arch eq "x86") {
8083 $MinGW_Opts{"-D_M_IX86=300"}=1;
8084 }
8085 elsif($Arch eq "x86_64") {
8086 $MinGW_Opts{"-D_M_AMD64=300"}=1;
8087 }
8088 elsif($Arch eq "ia64") {
8089 $MinGW_Opts{"-D_M_IA64=300"}=1;
8090 }
8091 return join(" ", keys(%MinGW_Opts));
8092 }
8093 return "";
8094}
8095
8096my %C_Structure = map {$_=>1} (
8097# FIXME: Can't separate union and struct data types before dumping,
8098# so it sometimes cause compilation errors for unknown reason
8099# when trying to declare TYPE* tmp_add_class_N
8100# This is a list of such structures + list of other C structures
8101 "sigval",
8102 "sigevent",
8103 "sigaction",
8104 "sigvec",
8105 "sigstack",
8106 "timeval",
8107 "timezone",
8108 "rusage",
8109 "rlimit",
8110 "wait",
8111 "flock",
8112 "stat",
8113 "_stat",
8114 "stat32",
8115 "_stat32",
8116 "stat64",
8117 "_stat64",
8118 "_stati64",
8119 "if_nameindex",
8120 "usb_device",
8121 "sigaltstack",
8122 "sysinfo",
8123 "timeLocale",
8124 "tcp_debug",
8125 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008126 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008127 "timespec",
8128 "random_data",
8129 "drand48_data",
8130 "_IO_marker",
8131 "_IO_FILE",
8132 "lconv",
8133 "sched_param",
8134 "tm",
8135 "itimerspec",
8136 "_pthread_cleanup_buffer",
8137 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008138 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008139 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008140 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008141 "sigcontext",
8142 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008143 # Mac
8144 "_timex",
8145 "_class_t",
8146 "_category_t",
8147 "_class_ro_t",
8148 "_protocol_t",
8149 "_message_ref_t",
8150 "_super_message_ref_t",
8151 "_ivar_t",
8152 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008153);
8154
8155sub getCompileCmd($$$)
8156{
8157 my ($Path, $Opt, $Inc) = @_;
8158 my $GccCall = $GCC_PATH;
8159 if($Opt) {
8160 $GccCall .= " ".$Opt;
8161 }
8162 $GccCall .= " -x ";
8163 if($OSgroup eq "macos") {
8164 $GccCall .= "objective-";
8165 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008166
8167 if($EMERGENCY_MODE_48)
8168 { # workaround for GCC 4.8 (C only)
8169 $GccCall .= "c++";
8170 }
8171 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008172 { # compile as "C++" header
8173 # to obtain complete dump using GCC 4.0
8174 $GccCall .= "c++-header";
8175 }
8176 else
8177 { # compile as "C++" source
8178 # GCC 3.3 cannot compile headers
8179 $GccCall .= "c++";
8180 }
8181 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008182 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008183 $GccCall .= " ".$Opts;
8184 }
8185 # allow extra qualifications
8186 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008187 $GccCall .= " -fpermissive";
8188 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008189 if($NoStdInc)
8190 {
8191 $GccCall .= " -nostdinc";
8192 $GccCall .= " -nostdinc++";
8193 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008194 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008195 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008196 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008197 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008198 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008199 if($Inc)
8200 { # include paths
8201 $GccCall .= " ".$Inc;
8202 }
8203 return $GccCall;
8204}
8205
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008206sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008207{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008208 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008209 my %HeaderElems = (
8210 # Types
8211 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008212 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008213 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8214 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008215 "time.h" => ["time_t"],
8216 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008217 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8218 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008219 "stdbool.h" => ["_Bool"],
8220 "rpc/xdr.h" => ["bool_t"],
8221 "in_systm.h" => ["n_long", "n_short"],
8222 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008223 "arpa/inet.h" => ["fw_src", "ip_src"],
8224 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008225 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008226 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008227 );
8228 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008229 foreach (keys(%HeaderElems))
8230 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008231 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008232 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008233 }
8234 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008235 my %Types = ();
8236 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8237 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008238 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008239 }
8240 if(keys(%Types))
8241 {
8242 my %AddHeaders = ();
8243 foreach my $Type (keys(%Types))
8244 {
8245 if(my $Header = $AutoPreamble{$Type})
8246 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008247 if(my $Path = identifyHeader($Header, $LibVersion))
8248 {
8249 if(skipHeader($Path, $LibVersion)) {
8250 next;
8251 }
8252 $Path = path_format($Path, $OSgroup);
8253 $AddHeaders{$Path}{"Type"} = $Type;
8254 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008255 }
8256 }
8257 }
8258 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008259 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008260 }
8261 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008262 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008263}
8264
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008265sub checkCTags($)
8266{
8267 my $Path = $_[0];
8268 if(not $Path) {
8269 return;
8270 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008271 my $CTags = undef;
8272
8273 if($OSgroup eq "bsd")
8274 { # use ectags on BSD
8275 $CTags = get_CmdPath("ectags");
8276 if(not $CTags) {
8277 printMsg("WARNING", "can't find \'ectags\' program");
8278 }
8279 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008280 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008281 $CTags = get_CmdPath("ctags");
8282 }
8283 if(not $CTags)
8284 {
8285 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008286 return;
8287 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008288
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008289 if($OSgroup ne "linux")
8290 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008291 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8292 if($Info!~/exuberant/i)
8293 {
8294 printMsg("WARNING", "incompatible version of \'ctags\' program");
8295 return;
8296 }
8297 }
8298
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008299 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008300 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008301 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008302 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008303 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008304 open(CTAGS, "<", $Out);
8305 while(my $Line = <CTAGS>)
8306 {
8307 chomp($Line);
8308 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008309 if(defined $Intrinsic_Keywords{$Name})
8310 { # noise
8311 next;
8312 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008313 if($Type eq "n")
8314 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008315 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008316 next;
8317 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008318 if(index($Scpe, "struct:")==0) {
8319 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008320 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008321 if(index($Scpe, "namespace:")==0)
8322 {
8323 if($Scpe=~s/\Anamespace://) {
8324 $Name = $Scpe."::".$Name;
8325 }
8326 }
8327 $TUnit_NameSpaces{$Version}{$Name} = 1;
8328 }
8329 elsif($Type eq "p")
8330 {
8331 if(not $Scpe or index($Scpe, "namespace:")==0) {
8332 $TUnit_Funcs{$Version}{$Name} = 1;
8333 }
8334 }
8335 elsif($Type eq "x")
8336 {
8337 if(not $Scpe or index($Scpe, "namespace:")==0) {
8338 $TUnit_Vars{$Version}{$Name} = 1;
8339 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008340 }
8341 }
8342 close(CTAGS);
8343}
8344
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008345sub preChange($$)
8346{
8347 my ($HeaderPath, $IncStr) = @_;
8348
8349 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8350 my $Content = undef;
8351
8352 if($OStarget eq "windows"
8353 and get_dumpmachine($GCC_PATH)=~/mingw/i
8354 and $MinGWMode{$Version}!=-1)
8355 { # modify headers to compile by MinGW
8356 if(not $Content)
8357 { # preprocessing
8358 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8359 }
8360 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8361 { # __asm { ... }
8362 $MinGWMode{$Version}=1;
8363 }
8364 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8365 { # comments after preprocessing
8366 $MinGWMode{$Version}=1;
8367 }
8368 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8369 { # 0xffui8
8370 $MinGWMode{$Version}=1;
8371 }
8372
8373 if($MinGWMode{$Version}) {
8374 printMsg("INFO", "Using MinGW compatibility mode");
8375 }
8376 }
8377
8378 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8379 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8380 { # rename C++ keywords in C code
8381 # disable this code by -cpp-compatible option
8382 if(not $Content)
8383 { # preprocessing
8384 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8385 }
8386 my $RegExp_C = join("|", keys(%CppKeywords_C));
8387 my $RegExp_F = join("|", keys(%CppKeywords_F));
8388 my $RegExp_O = join("|", keys(%CppKeywords_O));
8389
8390 my $Detected = undef;
8391
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008392 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 +04008393 { # MATCH:
8394 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008395 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008396 # unsigned private: 8;
8397 # DO NOT MATCH:
8398 # #pragma GCC visibility push(default)
8399 $CppMode{$Version} = 1;
8400 $Detected = "$1$2$3$4" if(not defined $Detected);
8401 }
8402 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8403 { # MATCH:
8404 # int delete(...);
8405 # int explicit(...);
8406 # DO NOT MATCH:
8407 # void operator delete(...)
8408 $CppMode{$Version} = 1;
8409 $Detected = "$1$2$3" if(not defined $Detected);
8410 }
8411 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8412 { # MATCH:
8413 # int bool;
8414 # DO NOT MATCH:
8415 # bool X;
8416 # return *this;
8417 # throw;
8418 $CppMode{$Version} = 1;
8419 $Detected = "$1$2$3" if(not defined $Detected);
8420 }
8421 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8422 { # MATCH:
8423 # int operator(...);
8424 # DO NOT MATCH:
8425 # int operator()(...);
8426 $CppMode{$Version} = 1;
8427 $Detected = "$1$2$3" if(not defined $Detected);
8428 }
8429 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8430 { # MATCH:
8431 # int foo(int operator);
8432 # int foo(int operator, int other);
8433 # DO NOT MATCH:
8434 # int operator,(...);
8435 $CppMode{$Version} = 1;
8436 $Detected = "$1$2$3" if(not defined $Detected);
8437 }
8438 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8439 { # MATCH:
8440 # int foo(gboolean *bool);
8441 # DO NOT MATCH:
8442 # void setTabEnabled(int index, bool);
8443 $CppMode{$Version} = 1;
8444 $Detected = "$1$2$3" if(not defined $Detected);
8445 }
8446 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8447 { # MATCH:
8448 # int foo(int* this);
8449 # int bar(int this);
8450 # int baz(int throw);
8451 # DO NOT MATCH:
8452 # foo(X, this);
8453 $CppMode{$Version} = 1;
8454 $Detected = "$1$2$3$4" if(not defined $Detected);
8455 }
8456 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8457 { # MATCH:
8458 # struct template {...};
8459 # extern template foo(...);
8460 $CppMode{$Version} = 1;
8461 $Detected = "$1$2" if(not defined $Detected);
8462 }
8463
8464 if($CppMode{$Version} == 1)
8465 {
8466 if($Debug)
8467 {
8468 $Detected=~s/\A\s+//g;
8469 printMsg("INFO", "Detected code: \"$Detected\"");
8470 }
8471 }
8472
8473 # remove typedef enum NAME NAME;
8474 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8475 my $N = 0;
8476 while($N<=$#FwdTypedefs-1)
8477 {
8478 my $S = $FwdTypedefs[$N];
8479 if($S eq $FwdTypedefs[$N+1])
8480 {
8481 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008482 $CppMode{$Version} = 1;
8483
8484 if($Debug) {
8485 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8486 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008487 }
8488 $N+=2;
8489 }
8490
8491 if($CppMode{$Version}==1) {
8492 printMsg("INFO", "Using C++ compatibility mode");
8493 }
8494 }
8495
8496 if($CppMode{$Version}==1
8497 or $MinGWMode{$Version}==1)
8498 {
8499 my $IPath = $TMP_DIR."/dump$Version.i";
8500 writeFile($IPath, $Content);
8501 return $IPath;
8502 }
8503
8504 return undef;
8505}
8506
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008507sub getDump()
8508{
8509 if(not $GCC_PATH) {
8510 exitStatus("Error", "internal error - GCC path is not set");
8511 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008512
8513 my @Headers = keys(%{$Registered_Headers{$Version}});
8514 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8515
8516 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8517
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008518 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008519 my $HeaderPath = $TmpHeaderPath;
8520
8521 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008522 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008523 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8524 {
8525 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008526 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008527 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008528 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008529 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8530 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008531 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008532 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008533 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008534 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8535 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8536 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008537 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008538 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008539
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008540 if($ExtraInfo)
8541 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008542 if($IncludeString) {
8543 writeFile($ExtraInfo."/include-string", $IncludeString);
8544 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008545 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8546 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008547
8548 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8549 {
8550 my $REDIR = "";
8551 foreach my $P1 (sort @Redirects) {
8552 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8553 }
8554 writeFile($ExtraInfo."/include-redirect", $REDIR);
8555 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008556 }
8557
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008558 if(not keys(%{$TargetHeaders{$Version}}))
8559 { # Target headers
8560 addTargetHeaders($Version);
8561 }
8562
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008563 # clean memory
8564 %RecursiveIncludes = ();
8565 %Header_Include_Prefix = ();
8566 %Header_Includes = ();
8567
8568 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008569 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008570 delete($Cache{"detect_header_includes"});
8571 delete($Cache{"selectSystemHeader"});
8572
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008573 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008574 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8575 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008576
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008577 if($ExtraInfo)
8578 { # extra information for other tools
8579 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8580 }
8581
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008582 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008583 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008584 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008585
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008586 if($COMMON_LANGUAGE{$Version} eq "C++") {
8587 checkCTags($Pre);
8588 }
8589
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008590 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8591 { # try to correct the preprocessor output
8592 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008593 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008594
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008595 if($COMMON_LANGUAGE{$Version} eq "C++")
8596 { # add classes and namespaces to the dump
8597 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008598 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008599 or $MinGWMode{$Version}==1) {
8600 $CHdump .= " -fpreprocessed";
8601 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008602 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008603 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008604 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008605 chdir($ORIG_DIR);
8606 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8607 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008608 my $Content = readFile($ClassDump);
8609 foreach my $ClassInfo (split(/\n\n/, $Content))
8610 {
8611 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8612 {
8613 my $CName = $1;
8614 next if($CName=~/\A(__|_objc_|_opaque_)/);
8615 $TUnit_NameSpaces{$Version}{$CName} = -1;
8616 if($CName=~/\A[\w:]+\Z/)
8617 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008618 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008619 }
8620 if($CName=~/(\w[\w:]*)::/)
8621 { # namespaces
8622 my $NS = $1;
8623 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8624 $TUnit_NameSpaces{$Version}{$NS} = 1;
8625 }
8626 }
8627 }
8628 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8629 { # read v-tables (advanced approach)
8630 my ($CName, $VTable) = ($1, $2);
8631 $ClassVTable_Content{$Version}{$CName} = $VTable;
8632 }
8633 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008634 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8635 { # add user-defined namespaces
8636 $TUnit_NameSpaces{$Version}{$NS} = 1;
8637 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008638 if($Debug)
8639 { # debug mode
8640 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008641 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008642 }
8643 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008644 }
8645
8646 # add namespaces and classes
8647 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8648 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008649 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008650 }
8651 # some GCC versions don't include class methods to the TU dump by default
8652 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008653 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008654 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8655 {
8656 next if($C_Structure{$CName});
8657 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008658 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008659 if(not $Force and $GCC_44
8660 and $OSgroup eq "linux")
8661 { # optimization for linux with GCC >= 4.4
8662 # disable this code by -force option
8663 if(index($CName, "::")!=-1)
8664 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008665 next;
8666 }
8667 }
8668 else
8669 {
8670 if($CName=~/\A(.+)::[^:]+\Z/
8671 and $TUnit_Classes{$Version}{$1})
8672 { # classes inside other classes
8673 next;
8674 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008675 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008676 if(defined $TUnit_Funcs{$Version}{$CName})
8677 { # the same name for a function and type
8678 next;
8679 }
8680 if(defined $TUnit_Vars{$Version}{$CName})
8681 { # the same name for a variable and type
8682 next;
8683 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008684 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8685 }
8686 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008687 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008688 }
8689 }
8690 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8691 # create TU dump
8692 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008693 if($UserLang eq "C") {
8694 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8695 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008696 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008697 or $MinGWMode{$Version}==1) {
8698 $TUdump .= " -fpreprocessed";
8699 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008700 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008701 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8702 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008703 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008704 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008705 if($?)
8706 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008707 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008708 { # try to recompile
8709 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008710 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008711 and index($Errors, "c99_")!=-1
8712 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008713 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008714 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008715
8716 if($Debug)
8717 {
8718 # printMsg("INFO", $Errors);
8719 }
8720
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008721 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008722 resetLogging($Version);
8723 $TMP_DIR = tempdir(CLEANUP=>1);
8724 return getDump();
8725 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008726 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008727 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008728 { # add auto preamble headers and try again
8729 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008730 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008731 foreach my $Num (0 .. $#Headers)
8732 {
8733 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008734 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8735 {
8736 push_U($Include_Preamble{$Version}, $Path);
8737 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008738 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008739 }
8740 resetLogging($Version);
8741 $TMP_DIR = tempdir(CLEANUP=>1);
8742 return getDump();
8743 }
8744 elsif($Cpp0xMode{$Version}!=-1
8745 and ($Errors=~/\Q-std=c++0x\E/
8746 or $Errors=~/is not a class or namespace/))
8747 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008748 if(check_gcc($GCC_PATH, "4.6"))
8749 {
8750 $Cpp0xMode{$Version}=-1;
8751 printMsg("INFO", "Enabling c++0x mode");
8752 resetLogging($Version);
8753 $TMP_DIR = tempdir(CLEANUP=>1);
8754 $CompilerOptions{$Version} .= " -std=c++0x";
8755 return getDump();
8756 }
8757 else {
8758 printMsg("WARNING", "Probably c++0x construction detected");
8759 }
8760
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008761 }
8762 elsif($MinGWMode{$Version}==1)
8763 { # disable MinGW mode and try again
8764 $MinGWMode{$Version}=-1;
8765 resetLogging($Version);
8766 $TMP_DIR = tempdir(CLEANUP=>1);
8767 return getDump();
8768 }
8769 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008770 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008771 else {
8772 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008773 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008774 printMsg("ERROR", "some errors occurred when compiling headers");
8775 printErrorLog($Version);
8776 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008777 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008778 }
8779 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008780 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008781 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008782
8783 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8784 return $TUs[0];
8785 }
8786 else
8787 {
8788 my $Msg = "can't compile header(s)";
8789 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8790 $Msg .= "\nDid you install G++?";
8791 }
8792 exitStatus("Cannot_Compile", $Msg);
8793 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008794}
8795
8796sub cmd_file($)
8797{
8798 my $Path = $_[0];
8799 return "" if(not $Path or not -e $Path);
8800 if(my $CmdPath = get_CmdPath("file")) {
8801 return `$CmdPath -b \"$Path\"`;
8802 }
8803 return "";
8804}
8805
8806sub getIncString($$)
8807{
8808 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008809 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008810 my $String = "";
8811 foreach (@{$ArrRef}) {
8812 $String .= " ".inc_opt($_, $Style);
8813 }
8814 return $String;
8815}
8816
8817sub getIncPaths(@)
8818{
8819 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008820 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008821 if($INC_PATH_AUTODETECT{$Version})
8822 { # auto-detecting dependencies
8823 my %Includes = ();
8824 foreach my $HPath (@HeaderPaths)
8825 {
8826 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8827 {
8828 if($Skip_Include_Paths{$Version}{$Dir}) {
8829 next;
8830 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008831 if($SystemRoot)
8832 {
8833 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8834 next;
8835 }
8836 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008837 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008838 }
8839 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008840 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008841 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008842 }
8843 }
8844 else
8845 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008846 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008847 }
8848 return \@IncPaths;
8849}
8850
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008851sub push_U($@)
8852{ # push unique
8853 if(my $Array = shift @_)
8854 {
8855 if(@_)
8856 {
8857 my %Exist = map {$_=>1} @{$Array};
8858 foreach my $Elem (@_)
8859 {
8860 if(not defined $Exist{$Elem})
8861 {
8862 push(@{$Array}, $Elem);
8863 $Exist{$Elem} = 1;
8864 }
8865 }
8866 }
8867 }
8868}
8869
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008870sub callPreprocessor($$$)
8871{
8872 my ($Path, $Inc, $LibVersion) = @_;
8873 return "" if(not $Path or not -f $Path);
8874 my $IncludeString=$Inc;
8875 if(not $Inc) {
8876 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8877 }
8878 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008879 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008880 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008881 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008882}
8883
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008884sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008885{ # native "find" is much faster than File::Find (~6x)
8886 # also the File::Find doesn't support --maxdepth N option
8887 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008888 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008889 return () if(not $Path or not -e $Path);
8890 if($OSgroup eq "windows")
8891 {
8892 my $DirCmd = get_CmdPath("dir");
8893 if(not $DirCmd) {
8894 exitStatus("Not_Found", "can't find \"dir\" command");
8895 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008896 $Path = get_abs_path($Path);
8897 $Path = path_format($Path, $OSgroup);
8898 my $Cmd = $DirCmd." \"$Path\" /B /O";
8899 if($MaxDepth!=1) {
8900 $Cmd .= " /S";
8901 }
8902 if($Type eq "d") {
8903 $Cmd .= " /AD";
8904 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008905 elsif($Type eq "f") {
8906 $Cmd .= " /A-D";
8907 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008908 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008909 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008910 {
8911 if(not $UseRegex)
8912 { # FIXME: how to search file names in MS shell?
8913 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008914 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008915 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008916 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008917 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008918 }
8919 my @AbsPaths = ();
8920 foreach my $File (@Files)
8921 {
8922 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008923 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008924 }
8925 if($Type eq "f" and not -f $File)
8926 { # skip dirs
8927 next;
8928 }
8929 push(@AbsPaths, path_format($File, $OSgroup));
8930 }
8931 if($Type eq "d") {
8932 push(@AbsPaths, $Path);
8933 }
8934 return @AbsPaths;
8935 }
8936 else
8937 {
8938 my $FindCmd = get_CmdPath("find");
8939 if(not $FindCmd) {
8940 exitStatus("Not_Found", "can't find a \"find\" command");
8941 }
8942 $Path = get_abs_path($Path);
8943 if(-d $Path and -l $Path
8944 and $Path!~/\/\Z/)
8945 { # for directories that are symlinks
8946 $Path.="/";
8947 }
8948 my $Cmd = $FindCmd." \"$Path\"";
8949 if($MaxDepth) {
8950 $Cmd .= " -maxdepth $MaxDepth";
8951 }
8952 if($Type) {
8953 $Cmd .= " -type $Type";
8954 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008955 if($Name and not $UseRegex)
8956 { # wildcards
8957 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008958 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008959 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008960 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008961 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8962 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008963 my @Files = split(/\n/, $Res);
8964 if($Name and $UseRegex)
8965 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008966 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008967 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008968 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008969 }
8970}
8971
8972sub unpackDump($)
8973{
8974 my $Path = $_[0];
8975 return "" if(not $Path or not -e $Path);
8976 $Path = get_abs_path($Path);
8977 $Path = path_format($Path, $OSgroup);
8978 my ($Dir, $FileName) = separate_path($Path);
8979 my $UnpackDir = $TMP_DIR."/unpack";
8980 rmtree($UnpackDir);
8981 mkpath($UnpackDir);
8982 if($FileName=~s/\Q.zip\E\Z//g)
8983 { # *.zip
8984 my $UnzipCmd = get_CmdPath("unzip");
8985 if(not $UnzipCmd) {
8986 exitStatus("Not_Found", "can't find \"unzip\" command");
8987 }
8988 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008989 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008990 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008991 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008992 }
8993 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008994 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008995 if(not @Contents) {
8996 exitStatus("Error", "can't extract \'$Path\'");
8997 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008998 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008999 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009000 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009001 { # *.tar.gz
9002 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 Ponomarenkod2ed4c62014-03-05 17:34:32 +040019819 if(not $CheckedArch{$LibVersion})
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
19843 if($OSgroup eq "windows")
19844 {
19845 my $DumpbinCmd = get_CmdPath("dumpbin");
19846 if(not $DumpbinCmd) {
19847 exitStatus("Not_Found", "can't find \"dumpbin\"");
19848 }
19849
19850 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19851 my $Out = `$Cmd`;
19852
19853 if($Out=~/(\w+)\smachine/)
19854 {
19855 if(my $Type = $MachineType{uc($1)})
19856 {
19857 return $Type;
19858 }
19859 }
19860 }
19861 elsif($OSgroup=~/linux|bsd/)
19862 {
19863 my $ObjdumpCmd = get_CmdPath("objdump");
19864 if(not $ObjdumpCmd) {
19865 exitStatus("Not_Found", "can't find \"objdump\"");
19866 }
19867
19868 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
19869 my $Out = `$Cmd`;
19870
19871 if($Out=~/architecture:\s+([\w\-\:]+)/)
19872 {
19873 my $Arch = $1;
19874 if($Arch=~s/\:(.+)//)
19875 {
19876 my $Suffix = $1;
19877
19878 if($Suffix eq "x86-64") {
19879 $Arch = $Suffix;
19880 }
19881
19882 if($Arch eq "powerpc")
19883 {
19884 if($Suffix eq "common64")
19885 {
19886 $Arch = "ppc64";
19887 }
19888 elsif($Suffix eq "common")
19889 {
19890 $Arch = "ppc32";
19891 }
19892 }
19893 }
19894
19895 if($Arch=~/i[3-7]86/) {
19896 $Arch = "x86";
19897 }
19898
19899 if($Arch eq "x86-64") {
19900 $Arch = "x86_64";
19901 }
19902
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019903 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019904 }
19905 }
19906 else
19907 { # macos, etc.
19908 # TODO
19909 }
19910
19911 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019912}
19913
19914sub getSONAME($)
19915{
19916 my $Path = $_[0];
19917 return if(not $Path);
19918 if(defined $Cache{"getSONAME"}{$Path}) {
19919 return $Cache{"getSONAME"}{$Path};
19920 }
19921 my $ObjdumpCmd = get_CmdPath("objdump");
19922 if(not $ObjdumpCmd) {
19923 exitStatus("Not_Found", "can't find \"objdump\"");
19924 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019925 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019926 if($OSgroup eq "windows") {
19927 $SonameCmd .= " | find \"SONAME\"";
19928 }
19929 else {
19930 $SonameCmd .= " | grep SONAME";
19931 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019932 if(my $SonameInfo = `$SonameCmd`)
19933 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019934 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19935 return ($Cache{"getSONAME"}{$Path} = $1);
19936 }
19937 }
19938 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019939}
19940
19941sub getSOPaths_Dest($$)
19942{
19943 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019944 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019945 return ();
19946 }
19947 if(-f $Dest)
19948 {
19949 if(not parse_libname($Dest, "name", $OStarget)) {
19950 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19951 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019952 registerObject($Dest, $LibVersion);
19953 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019954 return ($Dest);
19955 }
19956 elsif(-d $Dest)
19957 {
19958 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019959 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019960 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019961 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19962 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019963 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019964 { # all files and symlinks that match the name of a library
19965 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19966 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019967 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019968 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019969 }
19970 }
19971 }
19972 else
19973 { # search for all files and symlinks
19974 foreach my $Path (find_libs($Dest,"",""))
19975 {
19976 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019977 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019978 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019979 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019980 }
19981 if($OSgroup eq "macos")
19982 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019983 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019984 {
19985 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019986 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019987 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019988 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19989 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019990 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019991 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019992 }
19993 }
19994 }
19995 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019996 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019997 }
19998 else {
19999 return ();
20000 }
20001}
20002
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020003sub isCyclical($$)
20004{
20005 my ($Stack, $Value) = @_;
20006 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020007}
20008
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020009sub getGCC_Opts($)
20010{ # to use in module
20011 my $LibVersion = $_[0];
20012
20013 my @Opts = ();
20014
20015 if($CompilerOptions{$LibVersion})
20016 { # user-defined options
20017 push(@Opts, $CompilerOptions{$LibVersion});
20018 }
20019 if($GccOptions)
20020 { # additional
20021 push(@Opts, $GccOptions);
20022 }
20023
20024 if(@Opts) {
20025 return join(" ", @Opts);
20026 }
20027
20028 return undef;
20029}
20030
20031sub getArch_GCC($) # get_dumpmachine
20032{
20033 my $LibVersion = $_[0];
20034
20035 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
20036 return $Cache{"getArch_GCC"}{$LibVersion};
20037 }
20038
20039 my $Arch = undef;
20040
20041 if($GCC_PATH)
20042 {
20043 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
20044
20045 my $Cmd = $GCC_PATH." test.c -o test";
20046 if(my $Opts = getGCC_Opts($LibVersion))
20047 { # user-defined options
20048 $Cmd .= " ".$Opts;
20049 }
20050
20051 chdir($TMP_DIR);
20052 system($Cmd);
20053 chdir($ORIG_DIR);
20054
20055 $Arch = getArch_Object("$TMP_DIR/test");
20056
20057 unlink("$TMP_DIR/test.c");
20058 unlink("$TMP_DIR/test");
20059 }
20060
20061 if(not $Arch) {
20062 exitStatus("Error", "can't check ARCH type");
20063 }
20064
20065 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
20066}
20067
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020068sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020069{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020070 my $LibVersion = $_[0];
20071
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020072 my $Size = undef;
20073
20074 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020075 if(my $Arch = getArch($LibVersion))
20076 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020077 if($Arch=~/\A(x86_64|s390x|ppc64|ia64)\Z/) {
20078 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020079 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020080 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
20081 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020082 }
20083 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020084
20085 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020086 {
20087 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020088
20089 my $Cmd = $GCC_PATH." -E -dD empty.h";
20090 if(my $Opts = getGCC_Opts($LibVersion))
20091 { # user-defined options
20092 $Cmd .= " ".$Opts;
20093 }
20094
20095 chdir($TMP_DIR);
20096 my $Defines = `$Cmd`;
20097 chdir($ORIG_DIR);
20098
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020099 unlink("$TMP_DIR/empty.h");
20100
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020101 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
20102 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020103 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020104 }
20105 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
20106 { # GCC 3
20107 my $PTRDIFF = $1;
20108 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020109 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020110 }
20111 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020112 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020113 }
20114 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020115 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020116
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020117 if(not $Size) {
20118 exitStatus("Error", "can't check WORD size");
20119 }
20120
20121 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020122}
20123
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020124sub getWordSize($)
20125{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020126 return $WORD_SIZE{$_[0]};
20127}
20128
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020129sub majorVersion($)
20130{
20131 my $V = $_[0];
20132 return 0 if(not $V);
20133 my @VParts = split(/\./, $V);
20134 return $VParts[0];
20135}
20136
20137sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020138{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020139 my ($V1, $V2) = @_;
20140 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020141 my @V1Parts = split(/\./, $V1);
20142 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020143 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20144 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020145 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20146 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20147 }
20148 return -1 if($#V1Parts < $#V2Parts);
20149 return 1 if($#V1Parts > $#V2Parts);
20150 return 0;
20151}
20152
20153sub read_ABI_Dump($$)
20154{
20155 my ($LibVersion, $Path) = @_;
20156 return if(not $LibVersion or not -e $Path);
20157 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020158 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020159 { # input *.abi
20160 $FilePath = $Path;
20161 }
20162 else
20163 { # input *.abi.tar.gz
20164 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020165 if(not isDump_U($FilePath)) {
20166 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20167 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020168 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020169
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020170 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020171
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020172 my $Line = readLineNum($FilePath, 0);
20173 if($Line=~/xml/)
20174 { # XML format
20175 loadModule("XmlDump");
20176 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020177 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020178 else
20179 { # Perl Data::Dumper format (default)
20180 open(DUMP, $FilePath);
20181 local $/ = undef;
20182 my $Content = <DUMP>;
20183 close(DUMP);
20184
20185 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20186 { # remove temp file
20187 unlink($FilePath);
20188 }
20189 if($Content!~/};\s*\Z/) {
20190 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20191 }
20192 $ABI = eval($Content);
20193 if(not $ABI) {
20194 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20195 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020196 }
20197 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020198 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020199 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020200 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020201 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020202 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020203 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020204 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020205
20206 if($ABI->{"ABI_DUMP_VERSION"})
20207 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020208 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020209 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020210 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020211 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020212 }
20213 else
20214 { # support for old ABI dumps
20215 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020216 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020217 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020218 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020219 }
20220 if(majorVersion($DVersion)<2)
20221 { # support for old ABI dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020222 if($UseOldDumps)
20223 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020224 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
20225 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020226 }
20227 }
20228 else
20229 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020230 my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020231 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020232 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020233 }
20234 exitStatus("Dump_Version", $Msg);
20235 }
20236 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020237
20238 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20239 { # DWARF ABI Dump
20240 $UseConv_Real{$LibVersion}{"P"} = 1;
20241 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20242
20243 $UsedDump{$LibVersion}{"DWARF"} = 1;
20244
20245 $TargetComponent = "module";
20246 }
20247
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020248 if(not checkDump($LibVersion, "2.11"))
20249 { # old ABI dumps
20250 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020251 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020252 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020253 { # ABI dump created with --binary option
20254 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20255 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020256 else
20257 { # default
20258 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20259 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020260
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020261 if(defined $ABI->{"Mode"}
20262 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020263 { # --ext option
20264 $ExtendedCheck = 1;
20265 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020266 if($ABI->{"Extra"}) {
20267 $ExtraDump = 1;
20268 }
20269
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020270 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020271 {
20272 $UsedDump{$LibVersion}{"L"} = $Lang;
20273 setLanguage($LibVersion, $Lang);
20274 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020275 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020276 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020277 }
20278 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020279 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020280 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020281 if(not $TInfo)
20282 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020283 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020284 }
20285 my %Tid_TDid = ();
20286 foreach my $TDid (keys(%{$TInfo}))
20287 {
20288 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20289 {
20290 $MAX_ID = $Tid if($Tid>$MAX_ID);
20291 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020292 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020293 }
20294 }
20295 my %NewID = ();
20296 foreach my $Tid (keys(%Tid_TDid))
20297 {
20298 my @TDids = keys(%{$Tid_TDid{$Tid}});
20299 if($#TDids>=1)
20300 {
20301 foreach my $TDid (@TDids)
20302 {
20303 if($TDid) {
20304 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20305 }
20306 else
20307 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020308 my $ID = ++$MAX_ID;
20309
20310 $NewID{$TDid}{$Tid} = $ID;
20311 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20312 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020313 }
20314 }
20315 }
20316 else
20317 {
20318 my $TDid = $TDids[0];
20319 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20320 }
20321 }
20322 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20323 {
20324 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20325 if(defined $Info{"BaseType"})
20326 {
20327 my $Bid = $Info{"BaseType"}{"Tid"};
20328 my $BDid = $Info{"BaseType"}{"TDid"};
20329 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020330 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020331 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20332 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20333 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020334 }
20335 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020337 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020338 read_Machine_DumpInfo($ABI, $LibVersion);
20339 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020340 if(not $SymbolInfo{$LibVersion})
20341 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020342 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020343 }
20344 if(not keys(%{$SymbolInfo{$LibVersion}}))
20345 { # validation of old-version dumps
20346 if(not $ExtendedCheck) {
20347 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20348 }
20349 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020350 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020351 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020352 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020353 else
20354 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020355 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020356 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020357 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020358 }
20359 if(not $DepSymbols)
20360 { # Cannot reconstruct DepSymbols. This may result in false
20361 # positives if the old dump is for library 2. Not a problem if
20362 # old dumps are only from old libraries.
20363 $DepSymbols = {};
20364 }
20365 foreach my $Symbol (keys(%{$DepSymbols})) {
20366 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20367 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020368 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020369 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020370
20371 if(my $V = $TargetVersion{$LibVersion}) {
20372 $Descriptor{$LibVersion}{"Version"} = $V;
20373 }
20374 else {
20375 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20376 }
20377
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020378 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020379 if(not $SkipTypes{$LibVersion})
20380 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020381 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020382 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020383 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020384 if(not $SkipSymbols{$LibVersion})
20385 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020386 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020387 }
20388 if(not $SkipSymbols{$LibVersion})
20389 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020390 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020391 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020392 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
20393 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20394 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020395 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020396 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020397 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020398 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020399 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020400 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020401 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020402 if(not checkDump($LibVersion, "2.10.1")
20403 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020404 { # support for old ABI dumps: added target headers
20405 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020406 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020407 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020408 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020409 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020410 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020411 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020412 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020413 if(defined $ABI->{"GccConstants"})
20414 { # 3.0
20415 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20416 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20417 }
20418 }
20419
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020420 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020421 if(not $NestedNameSpaces{$LibVersion})
20422 { # support for old dumps
20423 # Cannot reconstruct NameSpaces. This may affect design
20424 # of the compatibility report.
20425 $NestedNameSpaces{$LibVersion} = {};
20426 }
20427 # target system type
20428 # needed to adopt HTML report
20429 if(not $DumpSystem)
20430 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020431 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020432 }
20433 # recreate environment
20434 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20435 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020436 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020437 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020438 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20439 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020440 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020441 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020442 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020443 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20444 {
20445 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20446 setLanguage($LibVersion, "C++");
20447 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020448 }
20449 }
20450 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020451 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20452 {
20453 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20454 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20455 }
20456 }
20457
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020458 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020459 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020460 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020461 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020462 {
20463 if(not $Symbol_Library{$LibVersion}{$MnglName}
20464 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20465 push(@VFunc, $MnglName);
20466 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020467 }
20468 }
20469 translateSymbols(@VFunc, $LibVersion);
20470 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020471 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20472
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020473 if(not checkDump($LibVersion, "3.0"))
20474 { # support for old ABI dumps
20475 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20476 {
20477 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20478 {
20479 if(ref($BaseType) eq "HASH") {
20480 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20481 }
20482 }
20483 }
20484 }
20485
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020486 if(not checkDump($LibVersion, "3.2"))
20487 { # support for old ABI dumps
20488 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20489 {
20490 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20491 {
20492 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20493 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20494 }
20495 }
20496 }
20497
20498 # repair target headers list
20499 delete($TargetHeaders{$LibVersion});
20500 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020501 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20502 }
20503 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20504 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020505 }
20506
20507 # non-target constants from anon enums
20508 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20509 {
20510 if(not $ExtraDump
20511 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20512 {
20513 delete($Constants{$LibVersion}{$Name});
20514 }
20515 }
20516 }
20517
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020518 if(not checkDump($LibVersion, "2.20"))
20519 { # support for old ABI dumps
20520 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20521 {
20522 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20523
20524 if($TType=~/Struct|Union|Enum|Typedef/)
20525 { # repair complex types first
20526 next;
20527 }
20528
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020529 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020530 {
20531 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20532 if($BType=~/Struct|Union|Enum/i)
20533 {
20534 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20535 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20536 }
20537 }
20538 }
20539 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20540 {
20541 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20542 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20543 if($TType=~/Struct|Union|Enum/) {
20544 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20545 }
20546 }
20547 }
20548
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020549 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020550 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020551 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20552 { # support for old ABI dumps < 2.0 (ACC 1.22)
20553 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20554 {
20555 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20556 {
20557 if($Access ne "public") {
20558 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20559 }
20560 }
20561 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20562 }
20563 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20564 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020565 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20566 { # support for old ABI dumps
20567 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20568 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020569 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20570 { # DWARF ABI Dumps
20571 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20572 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020573 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20574 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20575 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020576 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20577 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020578 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020579 foreach (keys(%{$TInfo{"Base"}})) {
20580 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020581 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020582 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020583 if($TInfo{"Type"} eq "MethodPtr")
20584 {
20585 if(defined $TInfo{"Param"})
20586 { # support for old ABI dumps <= 1.17
20587 if(not defined $TInfo{"Param"}{"0"})
20588 {
20589 my $Max = keys(%{$TInfo{"Param"}});
20590 foreach my $Pos (1 .. $Max) {
20591 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20592 }
20593 delete($TInfo{"Param"}{$Max});
20594 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20595 }
20596 }
20597 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020598 if($TInfo{"BaseType"} eq $TypeId)
20599 { # fix ABI dump
20600 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20601 }
20602 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020603 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020604 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020605 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020606 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20607 if(not $BName)
20608 { # broken type
20609 next;
20610 }
20611 if($TInfo{"Name"} eq $BName)
20612 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020613 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020614 next;
20615 }
20616 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20617 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020618 }
20619 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020620 }
20621 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20622 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020623 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020624 }
20625 }
20626
20627 if(not checkDump($LibVersion, "2.15"))
20628 { # support for old ABI dumps
20629 my %Dups = ();
20630 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20631 {
20632 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020633 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020634 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20635 { # remove template decls
20636 delete($SymbolInfo{$LibVersion}{$InfoId});
20637 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020638 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020639 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020640 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20641 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020642 { # templates
20643 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020644 }
20645 }
20646 }
20647
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020648 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20649 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020650 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20651 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20652 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20653 { # support for old ABI dumps (< 3.1)
20654 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20655 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20656 { # add "this" first parameter
20657 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20658 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20659
20660 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20661 {
20662 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20663 foreach my $Pos (reverse(0 .. $#Pos)) {
20664 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20665 }
20666 }
20667 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20668 }
20669 }
20670
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020671 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20672 { # ABI dumps have no mangled names for C-functions
20673 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20674 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020675 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20676 { # support for old ABI dumps
20677 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20678 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020679 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20680 { # DWARF ABI Dumps
20681 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20682 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020683 }
20684
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020685 $Descriptor{$LibVersion}{"Dump"} = 1;
20686}
20687
20688sub read_Machine_DumpInfo($$)
20689{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020690 my ($ABI, $LibVersion) = @_;
20691 if($ABI->{"Arch"}) {
20692 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020693 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020694 if($ABI->{"WordSize"}) {
20695 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020696 }
20697 else
20698 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020699 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020700 }
20701 if(not $WORD_SIZE{$LibVersion})
20702 { # support for old dumps (<1.23)
20703 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20704 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020705 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020706 }
20707 else
20708 {
20709 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020710 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020711 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020712 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20713 { # any "pointer"-type
20714 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020715 last;
20716 }
20717 }
20718 if($PSize)
20719 { # a pointer type size
20720 $WORD_SIZE{$LibVersion} = $PSize;
20721 }
20722 else {
20723 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20724 }
20725 }
20726 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020727 if($ABI->{"GccVersion"}) {
20728 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020729 }
20730}
20731
20732sub read_Libs_DumpInfo($$)
20733{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020734 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020735 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20736 if(not $Library_Symbol{$LibVersion})
20737 { # support for old dumps
20738 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20739 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020740 if(keys(%{$Library_Symbol{$LibVersion}})
20741 and not $DumpAPI) {
20742 $Descriptor{$LibVersion}{"Libs"} = "OK";
20743 }
20744}
20745
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020746sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020747{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020748 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020749
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020750 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020751 and not $DumpAPI) {
20752 $Descriptor{$LibVersion}{"Headers"} = "OK";
20753 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020754 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020755 { # headers info is stored in the old dumps in the different way
20756 if($UseOldDumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020757 and my $Name = $ABI->{"Headers"}{$Identity}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020758 { # support for old dumps: headers info corrected in 1.22
20759 $Identity = $Name;
20760 }
20761 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020762 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020763 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020764
20765 if(keys(%{$ABI->{"Sources"}})
20766 and not $DumpAPI) {
20767 $Descriptor{$LibVersion}{"Sources"} = "OK";
20768 }
20769 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
20770 { # headers info is stored in the old dumps in the different way
20771 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20772 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20773 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020774}
20775
20776sub find_libs($$$)
20777{
20778 my ($Path, $Type, $MaxDepth) = @_;
20779 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020780 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020781}
20782
20783sub createDescriptor($$)
20784{
20785 my ($LibVersion, $Path) = @_;
20786 if(not $LibVersion or not $Path
20787 or not -e $Path) {
20788 return "";
20789 }
20790 if(-d $Path)
20791 { # directory with headers files and shared objects
20792 return "
20793 <version>
20794 ".$TargetVersion{$LibVersion}."
20795 </version>
20796
20797 <headers>
20798 $Path
20799 </headers>
20800
20801 <libs>
20802 $Path
20803 </libs>";
20804 }
20805 else
20806 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020807 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020808 { # standard XML-descriptor
20809 return readFile($Path);
20810 }
20811 elsif(is_header($Path, 2, $LibVersion))
20812 { # header file
20813 return "
20814 <version>
20815 ".$TargetVersion{$LibVersion}."
20816 </version>
20817
20818 <headers>
20819 $Path
20820 </headers>
20821
20822 <libs>
20823 none
20824 </libs>";
20825 }
20826 elsif(parse_libname($Path, "name", $OStarget))
20827 { # shared object
20828 return "
20829 <version>
20830 ".$TargetVersion{$LibVersion}."
20831 </version>
20832
20833 <headers>
20834 none
20835 </headers>
20836
20837 <libs>
20838 $Path
20839 </libs>";
20840 }
20841 else
20842 { # standard XML-descriptor
20843 return readFile($Path);
20844 }
20845 }
20846}
20847
20848sub detect_lib_default_paths()
20849{
20850 my %LPaths = ();
20851 if($OSgroup eq "bsd")
20852 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020853 if(my $LdConfig = get_CmdPath("ldconfig"))
20854 {
20855 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20856 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020857 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20858 {
20859 my $Name = "lib".$1;
20860 if(not defined $LPaths{$Name}) {
20861 $LPaths{$Name} = $2;
20862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020863 }
20864 }
20865 }
20866 else {
20867 printMsg("WARNING", "can't find ldconfig");
20868 }
20869 }
20870 else
20871 {
20872 if(my $LdConfig = get_CmdPath("ldconfig"))
20873 {
20874 if($SystemRoot and $OSgroup eq "linux")
20875 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20876 if(-e $SystemRoot."/etc/ld.so.conf") {
20877 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20878 }
20879 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020880 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20881 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020882 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20883 {
20884 my ($Name, $Path) = ($1, $2);
20885 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020886 if(not defined $LPaths{$Name})
20887 { # get first element from the list of available paths
20888
20889 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20890 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20891 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20892
20893 $LPaths{$Name} = $Path;
20894 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020895 }
20896 }
20897 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020898 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020899 printMsg("WARNING", "can't find ldconfig");
20900 }
20901 }
20902 return \%LPaths;
20903}
20904
20905sub detect_bin_default_paths()
20906{
20907 my $EnvPaths = $ENV{"PATH"};
20908 if($OSgroup eq "beos") {
20909 $EnvPaths.=":".$ENV{"BETOOLS"};
20910 }
20911 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020912 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020913 {
20914 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020915 next if(not $Path);
20916 if($SystemRoot
20917 and $Path=~/\A\Q$SystemRoot\E\//)
20918 { # do NOT use binaries from target system
20919 next;
20920 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020921 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020922 }
20923}
20924
20925sub detect_inc_default_paths()
20926{
20927 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020928 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020929 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020930 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020931 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020932 next if(index($Line, "/cc1plus ")!=-1);
20933
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020934 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20935 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020936 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020937 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020938 if(index($Path, "c++")!=-1
20939 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020940 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020941 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020942 if(not defined $MAIN_CPP_DIR
20943 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20944 $MAIN_CPP_DIR = $Path;
20945 }
20946 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020947 elsif(index($Path, "gcc")!=-1) {
20948 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020949 }
20950 else
20951 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020952 if($Path=~/local[\/\\]+include/)
20953 { # local paths
20954 next;
20955 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020956 if($SystemRoot
20957 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20958 { # The GCC include path for user headers is not a part of the system root
20959 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20960 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20961 next;
20962 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020963 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020964 }
20965 }
20966 }
20967 unlink("$TMP_DIR/empty.h");
20968 return %DPaths;
20969}
20970
20971sub detect_default_paths($)
20972{
20973 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20974 my $Search = $_[0];
20975 if($Search!~/inc/) {
20976 $HSearch = 0;
20977 }
20978 if($Search!~/lib/) {
20979 $LSearch = 0;
20980 }
20981 if($Search!~/bin/) {
20982 $BSearch = 0;
20983 }
20984 if($Search!~/gcc/) {
20985 $GSearch = 0;
20986 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020987 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020988 { # <search_headers> section of the XML descriptor
20989 # do NOT search for systems headers
20990 $HSearch = 0;
20991 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020992 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020993 { # <search_headers> section of the XML descriptor
20994 # do NOT search for systems headers
20995 $LSearch = 0;
20996 }
20997 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20998 { # additional search paths
20999 next if($Type eq "include" and not $HSearch);
21000 next if($Type eq "lib" and not $LSearch);
21001 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021002 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021003 }
21004 if($OSgroup ne "windows")
21005 { # unix-like
21006 foreach my $Type ("include", "lib", "bin")
21007 { # automatic detection of system "devel" directories
21008 next if($Type eq "include" and not $HSearch);
21009 next if($Type eq "lib" and not $LSearch);
21010 next if($Type eq "bin" and not $BSearch);
21011 my ($UsrDir, $RootDir) = ("/usr", "/");
21012 if($SystemRoot and $Type ne "bin")
21013 { # 1. search for target headers and libraries
21014 # 2. use host commands: ldconfig, readelf, etc.
21015 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
21016 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021017 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021018 if(-d $RootDir."/".$Type)
21019 { # if "/lib" is symbolic link
21020 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021021 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021022 }
21023 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021024 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021025 }
21026 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021027 if(-d $UsrDir)
21028 {
21029 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021030 if(-d $UsrDir."/".$Type)
21031 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021032 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021033 }
21034 }
21035 }
21036 }
21037 if($BSearch)
21038 {
21039 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021040 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021041 }
21042 # check environment variables
21043 if($OSgroup eq "beos")
21044 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021045 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021046 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021047 if($_ eq ".") {
21048 next;
21049 }
21050 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
21051 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
21052 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021053 }
21054 }
21055 if($HSearch)
21056 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021057 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
21058 split(/:|;/, $ENV{"BEINCLUDES"})
21059 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021060 }
21061 if($LSearch)
21062 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021063 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
21064 split(/:|;/, $ENV{"BELIBRARIES"}),
21065 split(/:|;/, $ENV{"LIBRARY_PATH"})
21066 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021067 }
21068 }
21069 if($LSearch)
21070 { # using linker to get system paths
21071 if(my $LPaths = detect_lib_default_paths())
21072 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021073 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021074 foreach my $Name (keys(%{$LPaths}))
21075 {
21076 if($SystemRoot
21077 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
21078 { # wrong ldconfig configuration
21079 # check your <sysroot>/etc/ld.so.conf
21080 next;
21081 }
21082 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021083 if(my $Dir = get_dirname($LPaths->{$Name})) {
21084 $Dirs{$Dir} = 1;
21085 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021086 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021087 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021088 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021089 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021090 }
21091 if($BSearch)
21092 {
21093 if($CrossGcc)
21094 { # --cross-gcc=arm-linux-gcc
21095 if(-e $CrossGcc)
21096 { # absolute or relative path
21097 $GCC_PATH = get_abs_path($CrossGcc);
21098 }
21099 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
21100 { # command name
21101 $GCC_PATH = $CrossGcc;
21102 }
21103 else {
21104 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
21105 }
21106 if($GCC_PATH=~/\s/) {
21107 $GCC_PATH = "\"".$GCC_PATH."\"";
21108 }
21109 }
21110 }
21111 if($GSearch)
21112 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021113 if(not $CrossGcc)
21114 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021115 $GCC_PATH = get_CmdPath("gcc");
21116 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021117 if(not $GCC_PATH)
21118 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021119 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021120 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021121 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021122 { # select the latest version
21123 @GCCs = sort {$b cmp $a} @GCCs;
21124 if(check_gcc($GCCs[0], "3"))
21125 {
21126 $GCC_PATH = $GCCs[0];
21127 last;
21128 }
21129 }
21130 }
21131 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021132 if(not $GCC_PATH) {
21133 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21134 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021135
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021136 if(not $CheckObjectsOnly_Opt)
21137 {
21138 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
21139 {
21140 my $GccTarget = get_dumpmachine($GCC_PATH);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040021141 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021142 if($GccTarget=~/symbian/)
21143 {
21144 $OStarget = "symbian";
21145 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21146 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021147
21148 # check GCC version
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040021149 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021150 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040021151 # introduced in 4.8
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040021152 # fixed in 4.8.3
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021153 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
21154 $EMERGENCY_MODE_48 = 1;
21155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021156 }
21157 else {
21158 exitStatus("Error", "something is going wrong with the GCC compiler");
21159 }
21160 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021161 if($HSearch)
21162 {
21163 if(not $NoStdInc)
21164 { # do NOT search in GCC standard paths
21165 my %DPaths = detect_inc_default_paths();
21166 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21167 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21168 @DefaultIncPaths = @{$DPaths{"Inc"}};
21169 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021170 }
21171 }
21172 }
21173 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021174 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021175 my $IncPath = "/usr/include";
21176 if($SystemRoot) {
21177 $IncPath = $SystemRoot.$IncPath;
21178 }
21179 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021180 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021181 }
21182 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021183
21184 if($ExtraInfo)
21185 {
21186 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21187 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21188 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021189}
21190
21191sub getLIB_EXT($)
21192{
21193 my $Target = $_[0];
21194 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21195 return $Ext;
21196 }
21197 return $OS_LibExt{$LIB_TYPE}{"default"};
21198}
21199
21200sub getAR_EXT($)
21201{
21202 my $Target = $_[0];
21203 if(my $Ext = $OS_Archive{$Target}) {
21204 return $Ext;
21205 }
21206 return $OS_Archive{"default"};
21207}
21208
21209sub get_dumpversion($)
21210{
21211 my $Cmd = $_[0];
21212 return "" if(not $Cmd);
21213 if($Cache{"get_dumpversion"}{$Cmd}) {
21214 return $Cache{"get_dumpversion"}{$Cmd};
21215 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021216 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021217 chomp($V);
21218 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21219}
21220
21221sub get_dumpmachine($)
21222{
21223 my $Cmd = $_[0];
21224 return "" if(not $Cmd);
21225 if($Cache{"get_dumpmachine"}{$Cmd}) {
21226 return $Cache{"get_dumpmachine"}{$Cmd};
21227 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021228 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021229 chomp($Machine);
21230 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21231}
21232
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021233sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021234{
21235 my $Cmd = $_[0];
21236 return "" if(not $Cmd);
21237 my @Options = (
21238 "--version",
21239 "-help"
21240 );
21241 foreach my $Opt (@Options)
21242 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021243 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021244 if($Info) {
21245 return 1;
21246 }
21247 }
21248 return 0;
21249}
21250
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021251sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021252{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021253 my ($Cmd, $ReqVer) = @_;
21254 return 0 if(not $Cmd or not $ReqVer);
21255 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21256 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021257 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021258 if(my $GccVer = get_dumpversion($Cmd))
21259 {
21260 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21261 if(cmpVersions($GccVer, $ReqVer)>=0) {
21262 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21263 }
21264 }
21265 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021266}
21267
21268sub get_depth($)
21269{
21270 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021271 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021272 }
21273 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21274}
21275
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021276sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021277{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021278 return if($Cache{"registerGccHeaders"}); # this function should be called once
21279
21280 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021281 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021282 my @Headers = cmd_find($Path,"f");
21283 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21284 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021285 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021286 my $FileName = get_filename($HPath);
21287 if(not defined $DefaultGccHeader{$FileName})
21288 { # skip duplicated
21289 $DefaultGccHeader{$FileName} = $HPath;
21290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021291 }
21292 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021293 $Cache{"registerGccHeaders"} = 1;
21294}
21295
21296sub registerCppHeaders()
21297{
21298 return if($Cache{"registerCppHeaders"}); # this function should be called once
21299
21300 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021301 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021302 my @Headers = cmd_find($CppDir,"f");
21303 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21304 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021305 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021306 my $FileName = get_filename($Path);
21307 if(not defined $DefaultCppHeader{$FileName})
21308 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021309 $DefaultCppHeader{$FileName} = $Path;
21310 }
21311 }
21312 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021313 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021314}
21315
21316sub parse_libname($$$)
21317{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021318 return "" if(not $_[0]);
21319 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21320 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021321 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021322 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21323}
21324
21325sub parse_libname_I($$$)
21326{
21327 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021328
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021329 if($Target eq "symbian") {
21330 return parse_libname_symbian($Name, $Type);
21331 }
21332 elsif($Target eq "windows") {
21333 return parse_libname_windows($Name, $Type);
21334 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021335
21336 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021337 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021338 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021339 { # libSDL-1.2.so.0.7.1
21340 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021341 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021342 if($Type eq "name")
21343 { # libSDL-1.2
21344 # libwbxml2
21345 return $2;
21346 }
21347 elsif($Type eq "name+ext")
21348 { # libSDL-1.2.so
21349 # libwbxml2.so
21350 return $1;
21351 }
21352 elsif($Type eq "version")
21353 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021354 if(defined $7
21355 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021356 { # 0.7.1
21357 return $7;
21358 }
21359 else
21360 { # libc-2.5.so (=>2.5 version)
21361 my $MV = $5;
21362 $MV=~s/\A[\-\_]+//g;
21363 return $MV;
21364 }
21365 }
21366 elsif($Type eq "short")
21367 { # libSDL
21368 # libwbxml2
21369 return $3;
21370 }
21371 elsif($Type eq "shortest")
21372 { # SDL
21373 # wbxml
21374 return shortest_name($3);
21375 }
21376 }
21377 return "";# error
21378}
21379
21380sub parse_libname_symbian($$)
21381{
21382 my ($Name, $Type) = @_;
21383 my $Ext = getLIB_EXT("symbian");
21384 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21385 { # libpthread{00010001}.dso
21386 if($Type eq "name")
21387 { # libpthread{00010001}
21388 return $2;
21389 }
21390 elsif($Type eq "name+ext")
21391 { # libpthread{00010001}.dso
21392 return $1;
21393 }
21394 elsif($Type eq "version")
21395 { # 00010001
21396 my $V = $4;
21397 $V=~s/\{(.+)\}/$1/;
21398 return $V;
21399 }
21400 elsif($Type eq "short")
21401 { # libpthread
21402 return $3;
21403 }
21404 elsif($Type eq "shortest")
21405 { # pthread
21406 return shortest_name($3);
21407 }
21408 }
21409 return "";# error
21410}
21411
21412sub parse_libname_windows($$)
21413{
21414 my ($Name, $Type) = @_;
21415 my $Ext = getLIB_EXT("windows");
21416 if($Name=~/((.+?)\.$Ext)\Z/)
21417 { # netapi32.dll
21418 if($Type eq "name")
21419 { # netapi32
21420 return $2;
21421 }
21422 elsif($Type eq "name+ext")
21423 { # netapi32.dll
21424 return $1;
21425 }
21426 elsif($Type eq "version")
21427 { # DLL version embedded
21428 # at binary-level
21429 return "";
21430 }
21431 elsif($Type eq "short")
21432 { # netapi32
21433 return $2;
21434 }
21435 elsif($Type eq "shortest")
21436 { # netapi
21437 return shortest_name($2);
21438 }
21439 }
21440 return "";# error
21441}
21442
21443sub shortest_name($)
21444{
21445 my $Name = $_[0];
21446 # remove prefix
21447 $Name=~s/\A(lib|open)//;
21448 # remove suffix
21449 $Name=~s/[\W\d_]+\Z//i;
21450 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21451 return $Name;
21452}
21453
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021454sub createSymbolsList($$$$$)
21455{
21456 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
21457 read_ABI_Dump(1, $DPath);
21458 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021459 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021460 }
21461 my %SymbolHeaderLib = ();
21462 my $Total = 0;
21463 # Get List
21464 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21465 {
21466 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021467 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021468 next;
21469 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021470 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021471 { # skip other symbols
21472 next;
21473 }
21474 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21475 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021476 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021477 next;
21478 }
21479 my $DyLib = $Symbol_Library{1}{$Symbol};
21480 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021481 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021482 next;
21483 }
21484 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21485 $Total+=1;
21486 }
21487 # Draw List
21488 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21489 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21490 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21491 {
21492 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21493 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021494 my %NS_Symbol = ();
21495 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021496 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021497 }
21498 foreach my $NameSpace (sort keys(%NS_Symbol))
21499 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021500 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021501 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21502 foreach my $Symbol (@SortedInterfaces)
21503 {
21504 my $SubReport = "";
21505 my $Signature = get_Signature($Symbol, 1);
21506 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021507 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021508 }
21509 if($Symbol=~/\A(_Z|\?)/)
21510 {
21511 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021512 $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 +040021513 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021514 else {
21515 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21516 }
21517 }
21518 else
21519 {
21520 if($Signature) {
21521 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21522 }
21523 else {
21524 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21525 }
21526 }
21527 $SYMBOLS_LIST .= $SubReport;
21528 }
21529 }
21530 $SYMBOLS_LIST .= "<br/>\n";
21531 }
21532 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021533 # clear info
21534 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21535 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21536 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21537 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021538 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021539 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021540 my $CssStyles = readModule("Styles", "SymbolsList.css");
21541 my $JScripts = readModule("Scripts", "Sections.js");
21542 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021543 my $Title = "$LName: public symbols";
21544 my $Keywords = "$LName, API, symbols";
21545 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021546 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021547 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021548 <br/><br/><hr/>\n".getReportFooter($LName, 1)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021549 <div style='height:999px;'></div></body></html>";
21550 writeFile($SaveTo, $SYMBOLS_LIST);
21551}
21552
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021553sub add_target_libs($)
21554{
21555 foreach (@{$_[0]}) {
21556 $TargetLibs{$_} = 1;
21557 }
21558}
21559
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021560sub is_target_lib($)
21561{
21562 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021563 if(not $LName) {
21564 return 0;
21565 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021566 if($TargetLibraryName
21567 and $LName!~/\Q$TargetLibraryName\E/) {
21568 return 0;
21569 }
21570 if(keys(%TargetLibs)
21571 and not $TargetLibs{$LName}
21572 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21573 return 0;
21574 }
21575 return 1;
21576}
21577
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021578sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021579{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021580 my ($H, $V) = @_;
21581 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021582 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021583 if($TargetHeaders{$V}{$H}) {
21584 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021585 }
21586 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021587 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021588}
21589
21590sub checkVersionNum($$)
21591{
21592 my ($LibVersion, $Path) = @_;
21593 if(my $VerNum = $TargetVersion{$LibVersion}) {
21594 return $VerNum;
21595 }
21596 my $UsedAltDescr = 0;
21597 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021598 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021599 next if(isDump($Part)); # ABI dump
21600 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021601 my $VerNum = "";
21602 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021603 {
21604 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021605 $VerNum = parse_libname($Part, "version", $OStarget);
21606 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021607 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021608 }
21609 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021610 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
21611 {
21612 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021613 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021614 }
21615 if($VerNum ne "")
21616 {
21617 $TargetVersion{$LibVersion} = $VerNum;
21618 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021619 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021620 }
21621 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021622 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 +040021623 }
21624 return $TargetVersion{$LibVersion};
21625 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021626 }
21627 if($UsedAltDescr)
21628 {
21629 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021630 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021631 }
21632 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021633 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021634 }
21635 }
21636}
21637
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021638sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021639{
21640 my $Str = $_[0];
21641 return "" if(not $Str);
21642 $Str=~s/\Q$TargetLibraryName\E//g;
21643 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021644 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021645 return $2;
21646 }
21647 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
21648 return $V;
21649 }
21650 return "";
21651}
21652
21653sub readLibs($)
21654{
21655 my $LibVersion = $_[0];
21656 if($OStarget eq "windows")
21657 { # dumpbin.exe will crash
21658 # without VS Environment
21659 check_win32_env();
21660 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021661 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021662 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021663 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021664}
21665
21666sub dump_sorting($)
21667{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021668 my $Hash = $_[0];
21669 return [] if(not $Hash);
21670 my @Keys = keys(%{$Hash});
21671 return [] if($#Keys<0);
21672 if($Keys[0]=~/\A\d+\Z/)
21673 { # numbers
21674 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021675 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021676 else
21677 { # strings
21678 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021679 }
21680}
21681
21682sub printMsg($$)
21683{
21684 my ($Type, $Msg) = @_;
21685 if($Type!~/\AINFO/) {
21686 $Msg = $Type.": ".$Msg;
21687 }
21688 if($Type!~/_C\Z/) {
21689 $Msg .= "\n";
21690 }
21691 if($Quiet)
21692 { # --quiet option
21693 appendFile($COMMON_LOG_PATH, $Msg);
21694 }
21695 else
21696 {
21697 if($Type eq "ERROR") {
21698 print STDERR $Msg;
21699 }
21700 else {
21701 print $Msg;
21702 }
21703 }
21704}
21705
21706sub exitStatus($$)
21707{
21708 my ($Code, $Msg) = @_;
21709 printMsg("ERROR", $Msg);
21710 exit($ERROR_CODE{$Code});
21711}
21712
21713sub exitReport()
21714{ # the tool has run without any errors
21715 printReport();
21716 if($COMPILE_ERRORS)
21717 { # errors in headers may add false positives/negatives
21718 exit($ERROR_CODE{"Compile_Error"});
21719 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021720 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21721 { # --binary
21722 exit($ERROR_CODE{"Incompatible"});
21723 }
21724 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21725 { # --source
21726 exit($ERROR_CODE{"Incompatible"});
21727 }
21728 elsif($RESULT{"Source"}{"Problems"}
21729 or $RESULT{"Binary"}{"Problems"})
21730 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021731 exit($ERROR_CODE{"Incompatible"});
21732 }
21733 else {
21734 exit($ERROR_CODE{"Compatible"});
21735 }
21736}
21737
21738sub readRules($)
21739{
21740 my $Kind = $_[0];
21741 if(not -f $RULES_PATH{$Kind}) {
21742 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21743 }
21744 my $Content = readFile($RULES_PATH{$Kind});
21745 while(my $Rule = parseTag(\$Content, "rule"))
21746 {
21747 my $RId = parseTag(\$Rule, "id");
21748 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21749 foreach my $Prop (@Properties) {
21750 if(my $Value = parseTag(\$Rule, lc($Prop)))
21751 {
21752 $Value=~s/\n[ ]*//;
21753 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21754 }
21755 }
21756 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21757 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21758 }
21759 else {
21760 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21761 }
21762 }
21763}
21764
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021765sub getReportPath($)
21766{
21767 my $Level = $_[0];
21768 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21769 if($Level eq "Binary")
21770 {
21771 if($BinaryReportPath)
21772 { # --bin-report-path
21773 return $BinaryReportPath;
21774 }
21775 elsif($OutputReportPath)
21776 { # --report-path
21777 return $OutputReportPath;
21778 }
21779 else
21780 { # default
21781 return $Dir."/abi_compat_report.$ReportFormat";
21782 }
21783 }
21784 elsif($Level eq "Source")
21785 {
21786 if($SourceReportPath)
21787 { # --src-report-path
21788 return $SourceReportPath;
21789 }
21790 elsif($OutputReportPath)
21791 { # --report-path
21792 return $OutputReportPath;
21793 }
21794 else
21795 { # default
21796 return $Dir."/src_compat_report.$ReportFormat";
21797 }
21798 }
21799 else
21800 {
21801 if($OutputReportPath)
21802 { # --report-path
21803 return $OutputReportPath;
21804 }
21805 else
21806 { # default
21807 return $Dir."/compat_report.$ReportFormat";
21808 }
21809 }
21810}
21811
21812sub printStatMsg($)
21813{
21814 my $Level = $_[0];
21815 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21816}
21817
21818sub listAffected($)
21819{
21820 my $Level = $_[0];
21821 my $List = "";
21822 foreach (keys(%{$TotalAffected{$Level}}))
21823 {
21824 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21825 { # skip "Low"-severity problems
21826 next;
21827 }
21828 $List .= "$_\n";
21829 }
21830 my $Dir = get_dirname(getReportPath($Level));
21831 if($Level eq "Binary") {
21832 writeFile($Dir."/abi_affected.txt", $List);
21833 }
21834 elsif($Level eq "Source") {
21835 writeFile($Dir."/src_affected.txt", $List);
21836 }
21837}
21838
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021839sub printReport()
21840{
21841 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021842 createReport();
21843 if($JoinReport or $DoubleReport)
21844 {
21845 if($RESULT{"Binary"}{"Problems"}
21846 or $RESULT{"Source"}{"Problems"}) {
21847 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021848 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021849 else {
21850 printMsg("INFO", "result: COMPATIBLE");
21851 }
21852 printStatMsg("Binary");
21853 printStatMsg("Source");
21854 if($ListAffected)
21855 { # --list-affected
21856 listAffected("Binary");
21857 listAffected("Source");
21858 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021859 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021860 elsif($BinaryOnly)
21861 {
21862 if($RESULT{"Binary"}{"Problems"}) {
21863 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21864 }
21865 else {
21866 printMsg("INFO", "result: COMPATIBLE");
21867 }
21868 printStatMsg("Binary");
21869 if($ListAffected)
21870 { # --list-affected
21871 listAffected("Binary");
21872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021873 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021874 elsif($SourceOnly)
21875 {
21876 if($RESULT{"Source"}{"Problems"}) {
21877 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21878 }
21879 else {
21880 printMsg("INFO", "result: COMPATIBLE");
21881 }
21882 printStatMsg("Source");
21883 if($ListAffected)
21884 { # --list-affected
21885 listAffected("Source");
21886 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021887 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021888 if($StdOut)
21889 {
21890 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021891 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021892 printMsg("INFO", "compatibility report has been generated to stdout");
21893 }
21894 else
21895 { # default
21896 printMsg("INFO", "compatibility reports have been generated to stdout");
21897 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021898 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021899 else
21900 {
21901 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021902 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021903 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21904 }
21905 elsif($DoubleReport)
21906 { # default
21907 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21908 }
21909 elsif($BinaryOnly)
21910 { # --binary
21911 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21912 }
21913 elsif($SourceOnly)
21914 { # --source
21915 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21916 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021917 }
21918}
21919
21920sub check_win32_env()
21921{
21922 if(not $ENV{"DevEnvDir"}
21923 or not $ENV{"LIB"}) {
21924 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21925 }
21926}
21927
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021928sub diffSets($$)
21929{
21930 my ($S1, $S2) = @_;
21931 my @SK1 = keys(%{$S1});
21932 my @SK2 = keys(%{$S2});
21933 if($#SK1!=$#SK2) {
21934 return 1;
21935 }
21936 foreach my $K1 (@SK1)
21937 {
21938 if(not defined $S2->{$K1}) {
21939 return 1;
21940 }
21941 }
21942 return 0;
21943}
21944
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021945sub create_ABI_Dump()
21946{
21947 if(not -e $DumpAPI) {
21948 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21949 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021950
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021951 my @DParts = split(/\s*,\s*/, $DumpAPI);
21952 foreach my $Part (@DParts)
21953 {
21954 if(not -e $Part) {
21955 exitStatus("Access_Error", "can't access \'$Part\'");
21956 }
21957 }
21958 checkVersionNum(1, $DumpAPI);
21959 foreach my $Part (@DParts)
21960 {
21961 if(isDump($Part)) {
21962 read_ABI_Dump(1, $Part);
21963 }
21964 else {
21965 readDescriptor(1, createDescriptor(1, $Part));
21966 }
21967 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021968
21969 if(not $Descriptor{1}{"Version"})
21970 { # set to default: X
21971 $Descriptor{1}{"Version"} = "X";
21972 }
21973
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021974 initLogging(1);
21975 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021976
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021977 my $DumpPath = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi";
21978 $DumpPath .= ".".$AR_EXT; # gzipped by default
21979 if($OutputDumpPath)
21980 { # user defined path
21981 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021982 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021983 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21984
21985 if(not $Archive and not $StdOut)
21986 { # check archive utilities
21987 if($OSgroup eq "windows")
21988 { # using zip
21989 my $ZipCmd = get_CmdPath("zip");
21990 if(not $ZipCmd) {
21991 exitStatus("Not_Found", "can't find \"zip\"");
21992 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021993 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021994 else
21995 { # using tar and gzip
21996 my $TarCmd = get_CmdPath("tar");
21997 if(not $TarCmd) {
21998 exitStatus("Not_Found", "can't find \"tar\"");
21999 }
22000 my $GzipCmd = get_CmdPath("gzip");
22001 if(not $GzipCmd) {
22002 exitStatus("Not_Found", "can't find \"gzip\"");
22003 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022004 }
22005 }
22006
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022007 if(not $Descriptor{1}{"Dump"})
22008 {
22009 if(not $CheckHeadersOnly) {
22010 readLibs(1);
22011 }
22012 if($CheckHeadersOnly) {
22013 setLanguage(1, "C++");
22014 }
22015 if(not $CheckObjectsOnly) {
22016 searchForHeaders(1);
22017 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022018 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022019 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022020 if(not $Descriptor{1}{"Dump"})
22021 {
22022 if($Descriptor{1}{"Headers"}) {
22023 readHeaders(1);
22024 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022025 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022026 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022027 if(not keys(%{$SymbolInfo{1}}))
22028 { # check if created dump is valid
22029 if(not $ExtendedCheck and not $CheckObjectsOnly)
22030 {
22031 if($CheckHeadersOnly) {
22032 exitStatus("Empty_Set", "the set of public symbols is empty");
22033 }
22034 else {
22035 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
22036 }
22037 }
22038 }
22039 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022040 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022041 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
22042 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022043 if($ExtraDump)
22044 { # add unmangled names to the ABI dump
22045 my @Names = ();
22046 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22047 {
22048 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
22049 push(@Names, $MnglName);
22050 }
22051 }
22052 translateSymbols(@Names, 1);
22053 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22054 {
22055 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
22056 {
22057 if(my $Unmangled = $tr_name{$MnglName})
22058 {
22059 if($MnglName ne $Unmangled) {
22060 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
22061 }
22062 }
22063 }
22064 }
22065 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022066
22067 my %GccConstants = (); # built-in GCC constants
22068 foreach my $Name (keys(%{$Constants{1}}))
22069 {
22070 if(not defined $Constants{1}{$Name}{"Header"})
22071 {
22072 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
22073 delete($Constants{1}{$Name});
22074 }
22075 }
22076
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022077 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022078 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022079 "TypeInfo" => $TypeInfo{1},
22080 "SymbolInfo" => $SymbolInfo{1},
22081 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022082 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022083 "SymbolVersion" => $SymVer{1},
22084 "LibraryVersion" => $Descriptor{1}{"Version"},
22085 "LibraryName" => $TargetLibraryName,
22086 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022087 "SkipTypes" => $SkipTypes{1},
22088 "SkipSymbols" => $SkipSymbols{1},
22089 "SkipNameSpaces" => $SkipNameSpaces{1},
22090 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022091 "Headers" => \%HeadersInfo,
22092 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022093 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022094 "NameSpaces" => $NestedNameSpaces{1},
22095 "Target" => $OStarget,
22096 "Arch" => getArch(1),
22097 "WordSize" => $WORD_SIZE{1},
22098 "GccVersion" => get_dumpversion($GCC_PATH),
22099 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
22100 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
22101 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022102 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022103 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022104 }
22105 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022106 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022107 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022108 if($ExtendedCheck)
22109 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022110 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022111 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022112 if($BinaryOnly)
22113 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022114 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022115 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022116 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022117 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022118 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022119 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
22120 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022121 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022122
22123 my $ABI_DUMP = "";
22124 if($UseXML)
22125 {
22126 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022127 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022128 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022129 else
22130 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022131 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022133 if($StdOut)
22134 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022135 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022136 printMsg("INFO", "ABI dump has been generated to stdout");
22137 return;
22138 }
22139 else
22140 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022141 my ($DDir, $DName) = separate_path($DumpPath);
22142 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022143 if(not $Archive) {
22144 $DPath = $DumpPath;
22145 }
22146
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022147 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022148
22149 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022150 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022151 close(DUMP);
22152
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022153 if(not -s $DPath) {
22154 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
22155 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022156 if($Archive) {
22157 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022158 }
22159
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022160 if($OutputDumpPath) {
22161 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022162 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022163 else {
22164 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
22165 }
22166 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 +040022167 }
22168}
22169
22170sub quickEmptyReports()
22171{ # Quick "empty" reports
22172 # 4 times faster than merging equal dumps
22173 # NOTE: the dump contains the "LibraryVersion" attribute
22174 # if you change the version, then your dump will be different
22175 # OVERCOME: use -v1 and v2 options for comparing dumps
22176 # and don't change version in the XML descriptor (and dumps)
22177 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
22178 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
22179 {
22180 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
22181 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
22182 if($FilePath1 and $FilePath2)
22183 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022184 my $Line = readLineNum($FilePath1, 0);
22185 if($Line=~/xml/)
22186 { # XML format
22187 # is not supported yet
22188 return;
22189 }
22190
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022191 local $/ = undef;
22192
22193 open(DUMP1, $FilePath1);
22194 my $Content1 = <DUMP1>;
22195 close(DUMP1);
22196
22197 open(DUMP2, $FilePath2);
22198 my $Content2 = <DUMP2>;
22199 close(DUMP2);
22200
22201 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022202 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022203 # clean memory
22204 undef $Content2;
22205
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022206 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022207 my $ABIdump = eval($Content1);
22208
22209 # clean memory
22210 undef $Content1;
22211
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022212 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022213 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 +040022214 }
22215 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022216 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022217 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22218 }
22219 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022220 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022221 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22222 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022223 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022224 read_Libs_DumpInfo($ABIdump, 1);
22225 read_Machine_DumpInfo($ABIdump, 1);
22226 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022227
22228 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22229 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22230
22231 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
22232 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
22233
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022234 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22235 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
22236 exitReport();
22237 }
22238 }
22239 }
22240}
22241
22242sub initLogging($)
22243{
22244 my $LibVersion = $_[0];
22245 # create log directory
22246 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22247 if($OutputLogPath{$LibVersion})
22248 { # user-defined by -log-path option
22249 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22250 }
22251 if($LogMode ne "n") {
22252 mkpath($LOG_DIR);
22253 }
22254 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022255 if($Debug)
22256 { # debug directory
22257 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022258
22259 if(not $ExtraInfo)
22260 { # enable --extra-info
22261 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022263 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022264 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022265}
22266
22267sub writeLog($$)
22268{
22269 my ($LibVersion, $Msg) = @_;
22270 if($LogMode ne "n") {
22271 appendFile($LOG_PATH{$LibVersion}, $Msg);
22272 }
22273}
22274
22275sub resetLogging($)
22276{
22277 my $LibVersion = $_[0];
22278 if($LogMode!~/a|n/)
22279 { # remove old log
22280 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022281 if($Debug) {
22282 rmtree($DEBUG_PATH{$LibVersion});
22283 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022284 }
22285}
22286
22287sub printErrorLog($)
22288{
22289 my $LibVersion = $_[0];
22290 if($LogMode ne "n") {
22291 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22292 }
22293}
22294
22295sub isDump($)
22296{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022297 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz|\.zip|\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022298 return $1;
22299 }
22300 return 0;
22301}
22302
22303sub isDump_U($)
22304{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022305 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022306 return $1;
22307 }
22308 return 0;
22309}
22310
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022311sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022312{
22313 # read input XML descriptors or ABI dumps
22314 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022315 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022316 }
22317 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
22318 foreach my $Part (@DParts1)
22319 {
22320 if(not -e $Part) {
22321 exitStatus("Access_Error", "can't access \'$Part\'");
22322 }
22323 }
22324 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022325 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022326 }
22327 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
22328 foreach my $Part (@DParts2)
22329 {
22330 if(not -e $Part) {
22331 exitStatus("Access_Error", "can't access \'$Part\'");
22332 }
22333 }
22334 detect_default_paths("bin"); # to extract dumps
22335 if($#DParts1==0 and $#DParts2==0
22336 and isDump($Descriptor{1}{"Path"})
22337 and isDump($Descriptor{2}{"Path"}))
22338 { # optimization: equal ABI dumps
22339 quickEmptyReports();
22340 }
22341 checkVersionNum(1, $Descriptor{1}{"Path"});
22342 checkVersionNum(2, $Descriptor{2}{"Path"});
22343 printMsg("INFO", "preparation, please wait ...");
22344 foreach my $Part (@DParts1)
22345 {
22346 if(isDump($Part)) {
22347 read_ABI_Dump(1, $Part);
22348 }
22349 else {
22350 readDescriptor(1, createDescriptor(1, $Part));
22351 }
22352 }
22353 foreach my $Part (@DParts2)
22354 {
22355 if(isDump($Part)) {
22356 read_ABI_Dump(2, $Part);
22357 }
22358 else {
22359 readDescriptor(2, createDescriptor(2, $Part));
22360 }
22361 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022362
22363 if(not $Descriptor{1}{"Version"})
22364 { # set to default: X
22365 $Descriptor{1}{"Version"} = "X";
22366 }
22367
22368 if(not $Descriptor{2}{"Version"})
22369 { # set to default: Y
22370 $Descriptor{2}{"Version"} = "Y";
22371 }
22372
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022373 initLogging(1);
22374 initLogging(2);
22375 # check consistency
22376 if(not $Descriptor{1}{"Headers"}
22377 and not $Descriptor{1}{"Libs"}) {
22378 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
22379 }
22380 if(not $Descriptor{2}{"Headers"}
22381 and not $Descriptor{2}{"Libs"}) {
22382 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
22383 }
22384 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
22385 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
22386 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
22387 }
22388 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
22389 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
22390 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
22391 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022392 if(not $Descriptor{1}{"Headers"})
22393 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022394 if($CheckHeadersOnly_Opt) {
22395 exitStatus("Error", "can't find header files info in descriptor d1");
22396 }
22397 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022398 if(not $Descriptor{2}{"Headers"})
22399 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022400 if($CheckHeadersOnly_Opt) {
22401 exitStatus("Error", "can't find header files info in descriptor d2");
22402 }
22403 }
22404 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022405 or not $Descriptor{2}{"Headers"})
22406 {
22407 if(not $CheckObjectsOnly_Opt)
22408 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022409 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
22410 $CheckObjectsOnly = 1;
22411 }
22412 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022413 if(not $Descriptor{1}{"Libs"})
22414 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022415 if($CheckObjectsOnly_Opt) {
22416 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
22417 }
22418 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022419 if(not $Descriptor{2}{"Libs"})
22420 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022421 if($CheckObjectsOnly_Opt) {
22422 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
22423 }
22424 }
22425 if(not $Descriptor{1}{"Libs"}
22426 or not $Descriptor{2}{"Libs"})
22427 { # comparing standalone header files
22428 # comparing ABI dumps created with --headers-only
22429 if(not $CheckHeadersOnly_Opt)
22430 {
22431 printMsg("WARNING", "checking headers only");
22432 $CheckHeadersOnly = 1;
22433 }
22434 }
22435 if($UseDumps)
22436 { # --use-dumps
22437 # parallel processing
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022438 my $DumpPath1 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi.$AR_EXT";
22439 my $DumpPath2 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{2}{"Version"}.".abi.$AR_EXT";
22440
22441 unlink($DumpPath1);
22442 unlink($DumpPath2);
22443
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022444 my $pid = fork();
22445 if($pid)
22446 { # dump on two CPU cores
22447 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22448 if($RelativeDirectory{1}) {
22449 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22450 }
22451 if($OutputLogPath{1}) {
22452 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22453 }
22454 if($CrossGcc) {
22455 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22456 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022457 if($Quiet)
22458 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022459 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022460 @PARAMS = (@PARAMS, "-logging-mode", "a");
22461 }
22462 elsif($LogMode and $LogMode ne "w")
22463 { # "w" is default
22464 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022465 }
22466 if($ExtendedCheck) {
22467 @PARAMS = (@PARAMS, "-extended");
22468 }
22469 if($UserLang) {
22470 @PARAMS = (@PARAMS, "-lang", $UserLang);
22471 }
22472 if($TargetVersion{1}) {
22473 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22474 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022475 if($BinaryOnly) {
22476 @PARAMS = (@PARAMS, "-binary");
22477 }
22478 if($SourceOnly) {
22479 @PARAMS = (@PARAMS, "-source");
22480 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022481 if($SortDump) {
22482 @PARAMS = (@PARAMS, "-sort");
22483 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022484 if($DumpFormat and $DumpFormat ne "perl") {
22485 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22486 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022487 if($CheckHeadersOnly) {
22488 @PARAMS = (@PARAMS, "-headers-only");
22489 }
22490 if($CheckObjectsOnly) {
22491 @PARAMS = (@PARAMS, "-objects-only");
22492 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022493 if($Debug)
22494 {
22495 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022496 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022497 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022498 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022499 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022500 exit(1);
22501 }
22502 }
22503 else
22504 { # child
22505 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22506 if($RelativeDirectory{2}) {
22507 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22508 }
22509 if($OutputLogPath{2}) {
22510 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22511 }
22512 if($CrossGcc) {
22513 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22514 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022515 if($Quiet)
22516 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022517 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022518 @PARAMS = (@PARAMS, "-logging-mode", "a");
22519 }
22520 elsif($LogMode and $LogMode ne "w")
22521 { # "w" is default
22522 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022523 }
22524 if($ExtendedCheck) {
22525 @PARAMS = (@PARAMS, "-extended");
22526 }
22527 if($UserLang) {
22528 @PARAMS = (@PARAMS, "-lang", $UserLang);
22529 }
22530 if($TargetVersion{2}) {
22531 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22532 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022533 if($BinaryOnly) {
22534 @PARAMS = (@PARAMS, "-binary");
22535 }
22536 if($SourceOnly) {
22537 @PARAMS = (@PARAMS, "-source");
22538 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022539 if($SortDump) {
22540 @PARAMS = (@PARAMS, "-sort");
22541 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022542 if($DumpFormat and $DumpFormat ne "perl") {
22543 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22544 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022545 if($CheckHeadersOnly) {
22546 @PARAMS = (@PARAMS, "-headers-only");
22547 }
22548 if($CheckObjectsOnly) {
22549 @PARAMS = (@PARAMS, "-objects-only");
22550 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022551 if($Debug)
22552 {
22553 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022554 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022555 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022556 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022557 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022558 exit(1);
22559 }
22560 else {
22561 exit(0);
22562 }
22563 }
22564 waitpid($pid, 0);
22565 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022566 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22567 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022568 if($TargetLibraryFName ne $TargetLibraryName) {
22569 @CMP_PARAMS = (@CMP_PARAMS, "-l-full", $TargetLibraryFName);
22570 }
22571 if($ShowRetVal) {
22572 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22573 }
22574 if($CrossGcc) {
22575 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22576 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022577 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22578 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022579 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022580 }
22581 if($ReportFormat and $ReportFormat ne "html")
22582 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022583 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22584 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022585 if($OutputReportPath) {
22586 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22587 }
22588 if($BinaryReportPath) {
22589 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22590 }
22591 if($SourceReportPath) {
22592 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22593 }
22594 if($LoggingPath) {
22595 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22596 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022597 if($CheckHeadersOnly) {
22598 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22599 }
22600 if($CheckObjectsOnly) {
22601 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
22602 }
22603 if($BinaryOnly) {
22604 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22605 }
22606 if($SourceOnly) {
22607 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22608 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022609 if($Browse) {
22610 @CMP_PARAMS = (@CMP_PARAMS, "-browse", $Browse);
22611 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022612 if($OpenReport) {
22613 @CMP_PARAMS = (@CMP_PARAMS, "-open");
22614 }
22615 if($Debug)
22616 {
22617 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22618 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022619 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022620 system("perl", $0, @CMP_PARAMS);
22621 exit($?>>8);
22622 }
22623 if(not $Descriptor{1}{"Dump"}
22624 or not $Descriptor{2}{"Dump"})
22625 { # need GCC toolchain to analyze
22626 # header files and libraries
22627 detect_default_paths("inc|lib|gcc");
22628 }
22629 if(not $Descriptor{1}{"Dump"})
22630 {
22631 if(not $CheckHeadersOnly) {
22632 readLibs(1);
22633 }
22634 if($CheckHeadersOnly) {
22635 setLanguage(1, "C++");
22636 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022637 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022638 searchForHeaders(1);
22639 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022640 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022641 }
22642 if(not $Descriptor{2}{"Dump"})
22643 {
22644 if(not $CheckHeadersOnly) {
22645 readLibs(2);
22646 }
22647 if($CheckHeadersOnly) {
22648 setLanguage(2, "C++");
22649 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022650 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022651 searchForHeaders(2);
22652 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022653 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022654 }
22655 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22656 { # support for old ABI dumps
22657 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022658 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022659 {
22660 $WORD_SIZE{1} = $WORD_SIZE{2};
22661 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22662 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022663 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022664 {
22665 $WORD_SIZE{2} = $WORD_SIZE{1};
22666 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22667 }
22668 }
22669 elsif(not $WORD_SIZE{1}
22670 and not $WORD_SIZE{2})
22671 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022672 $WORD_SIZE{1} = "4";
22673 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022674 }
22675 if($Descriptor{1}{"Dump"})
22676 { # support for old ABI dumps
22677 prepareTypes(1);
22678 }
22679 if($Descriptor{2}{"Dump"})
22680 { # support for old ABI dumps
22681 prepareTypes(2);
22682 }
22683 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22684 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22685 }
22686 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022687 if(not $CheckObjectsOnly)
22688 {
22689 if($Descriptor{1}{"Headers"}
22690 and not $Descriptor{1}{"Dump"}) {
22691 readHeaders(1);
22692 }
22693 if($Descriptor{2}{"Headers"}
22694 and not $Descriptor{2}{"Dump"}) {
22695 readHeaders(2);
22696 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022697 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022698
22699 # clean memory
22700 %SystemHeaders = ();
22701 %mangled_name_gcc = ();
22702
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022703 prepareSymbols(1);
22704 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022705
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022706 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022707 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022708
22709 # Virtual Tables
22710 registerVTable(1);
22711 registerVTable(2);
22712
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022713 if(not checkDump(1, "1.22")
22714 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022715 { # support for old ABI dumps
22716 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22717 {
22718 if($ClassName=~/</)
22719 { # templates
22720 if(not defined $VirtualTable{1}{$ClassName})
22721 { # synchronize
22722 delete($VirtualTable{2}{$ClassName});
22723 }
22724 }
22725 }
22726 }
22727
22728 registerOverriding(1);
22729 registerOverriding(2);
22730
22731 setVirtFuncPositions(1);
22732 setVirtFuncPositions(2);
22733
22734 # Other
22735 addParamNames(1);
22736 addParamNames(2);
22737
22738 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022739}
22740
22741sub compareAPIs($)
22742{
22743 my $Level = $_[0];
22744 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022745 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022746 if($Level eq "Binary") {
22747 printMsg("INFO", "comparing ABIs ...");
22748 }
22749 else {
22750 printMsg("INFO", "comparing APIs ...");
22751 }
22752 if($CheckHeadersOnly
22753 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022754 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022755 detectAdded_H($Level);
22756 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022757 }
22758 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022759 { # added/removed in libs
22760 detectAdded($Level);
22761 detectRemoved($Level);
22762 }
22763 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022764 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022765 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022766 if(keys(%{$CheckedSymbols{$Level}})) {
22767 mergeConstants($Level);
22768 }
22769 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022770
22771 $Cache{"mergeTypes"} = (); # free memory
22772
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022773 if($CheckHeadersOnly
22774 or $Level eq "Source")
22775 { # added/removed in headers
22776 mergeHeaders($Level);
22777 }
22778 else
22779 { # added/removed in libs
22780 mergeLibs($Level);
22781 if($CheckImpl
22782 and $Level eq "Binary") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022783 mergeImpl();
22784 }
22785 }
22786}
22787
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022788sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022789{
22790 my %Opts = (
22791 "OStarget"=>$OStarget,
22792 "Debug"=>$Debug,
22793 "Quiet"=>$Quiet,
22794 "LogMode"=>$LogMode,
22795 "CheckHeadersOnly"=>$CheckHeadersOnly,
22796
22797 "SystemRoot"=>$SystemRoot,
22798 "MODULES_DIR"=>$MODULES_DIR,
22799 "GCC_PATH"=>$GCC_PATH,
22800 "TargetSysInfo"=>$TargetSysInfo,
22801 "CrossPrefix"=>$CrossPrefix,
22802 "TargetLibraryName"=>$TargetLibraryName,
22803 "CrossGcc"=>$CrossGcc,
22804 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022805 "NoStdInc"=>$NoStdInc,
22806
22807 "BinaryOnly" => $BinaryOnly,
22808 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022809 );
22810 return \%Opts;
22811}
22812
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022813sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022814{
22815 my %CODE_ERROR = reverse(%ERROR_CODE);
22816 return $CODE_ERROR{$_[0]};
22817}
22818
22819sub scenario()
22820{
22821 if($StdOut)
22822 { # enable quiet mode
22823 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022824 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022825 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022826 if(not $LogMode)
22827 { # default
22828 $LogMode = "w";
22829 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022830 if($UserLang)
22831 { # --lang=C++
22832 $UserLang = uc($UserLang);
22833 $COMMON_LANGUAGE{1}=$UserLang;
22834 $COMMON_LANGUAGE{2}=$UserLang;
22835 }
22836 if($LoggingPath)
22837 {
22838 $OutputLogPath{1} = $LoggingPath;
22839 $OutputLogPath{2} = $LoggingPath;
22840 if($Quiet) {
22841 $COMMON_LOG_PATH = $LoggingPath;
22842 }
22843 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022844 if($Quick) {
22845 $ADD_TMPL_INSTANCES = 0;
22846 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022847 if($OutputDumpPath)
22848 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022849 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022850 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22851 }
22852 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022853 if($BinaryOnly and $SourceOnly)
22854 { # both --binary and --source
22855 # is the default mode
22856 $DoubleReport = 1;
22857 $JoinReport = 0;
22858 $BinaryOnly = 0;
22859 $SourceOnly = 0;
22860 if($OutputReportPath)
22861 { # --report-path
22862 $DoubleReport = 0;
22863 $JoinReport = 1;
22864 }
22865 }
22866 elsif($BinaryOnly or $SourceOnly)
22867 { # --binary or --source
22868 $DoubleReport = 0;
22869 $JoinReport = 0;
22870 }
22871 if($UseXML)
22872 { # --xml option
22873 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022874 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022875 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022876 if($ReportFormat)
22877 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022878 $ReportFormat = lc($ReportFormat);
22879 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022880 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022881 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022882 if($ReportFormat eq "htm")
22883 { # HTM == HTML
22884 $ReportFormat = "html";
22885 }
22886 elsif($ReportFormat eq "xml")
22887 { # --report-format=XML equal to --xml
22888 $UseXML = 1;
22889 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022890 }
22891 else
22892 { # default: HTML
22893 $ReportFormat = "html";
22894 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022895 if($DumpFormat)
22896 { # validate
22897 $DumpFormat = lc($DumpFormat);
22898 if($DumpFormat!~/\A(xml|perl)\Z/) {
22899 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22900 }
22901 if($DumpFormat eq "xml")
22902 { # --dump-format=XML equal to --xml
22903 $UseXML = 1;
22904 }
22905 }
22906 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022907 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022908 $DumpFormat = "perl";
22909 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022910 if($Quiet and $LogMode!~/a|n/)
22911 { # --quiet log
22912 if(-f $COMMON_LOG_PATH) {
22913 unlink($COMMON_LOG_PATH);
22914 }
22915 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022916 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022917 $CheckUndefined = 1;
22918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022919 if($TestTool and $UseDumps)
22920 { # --test && --use-dumps == --test-dump
22921 $TestDump = 1;
22922 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022923 if($Tolerant)
22924 { # enable all
22925 $Tolerance = 1234;
22926 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022927 if($Help)
22928 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022929 HELP_MESSAGE();
22930 exit(0);
22931 }
22932 if($InfoMsg) {
22933 INFO_MESSAGE();
22934 exit(0);
22935 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022936 if($ShowVersion)
22937 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040022938 printMsg("INFO", "ABI Compliance Checker (ACC) $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 +040022939 exit(0);
22940 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022941 if($DumpVersion)
22942 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022943 printMsg("INFO", $TOOL_VERSION);
22944 exit(0);
22945 }
22946 if($ExtendedCheck) {
22947 $CheckHeadersOnly = 1;
22948 }
22949 if($SystemRoot_Opt)
22950 { # user defined root
22951 if(not -e $SystemRoot_Opt) {
22952 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22953 }
22954 $SystemRoot = $SystemRoot_Opt;
22955 $SystemRoot=~s/[\/]+\Z//g;
22956 if($SystemRoot) {
22957 $SystemRoot = get_abs_path($SystemRoot);
22958 }
22959 }
22960 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022961
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022962 if($SortDump)
22963 {
22964 $Data::Dumper::Useperl = 1;
22965 $Data::Dumper::Sortkeys = \&dump_sorting;
22966 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022967
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022968 if($TargetLibsPath)
22969 {
22970 if(not -f $TargetLibsPath) {
22971 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22972 }
22973 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22974 $TargetLibs{$Lib} = 1;
22975 }
22976 }
22977 if($TargetHeadersPath)
22978 { # --headers-list
22979 if(not -f $TargetHeadersPath) {
22980 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22981 }
22982 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22983 {
22984 $TargetHeaders{1}{$Header} = 1;
22985 $TargetHeaders{2}{$Header} = 1;
22986 }
22987 }
22988 if($TargetHeader)
22989 { # --header
22990 $TargetHeaders{1}{$TargetHeader} = 1;
22991 $TargetHeaders{2}{$TargetHeader} = 1;
22992 }
22993 if($TestTool
22994 or $TestDump)
22995 { # --test, --test-dump
22996 detect_default_paths("bin|gcc"); # to compile libs
22997 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022998 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
22999 $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023000 exit(0);
23001 }
23002 if($DumpSystem)
23003 { # --dump-system
23004 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023005 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023006 { # system XML descriptor
23007 if(not -f $DumpSystem) {
23008 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
23009 }
23010 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023011 foreach (@{$Ret->{"Tools"}})
23012 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023013 push_U($SystemPaths{"bin"}, $_);
23014 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023015 }
23016 if($Ret->{"CrossPrefix"}) {
23017 $CrossPrefix = $Ret->{"CrossPrefix"};
23018 }
23019 }
23020 elsif($SystemRoot_Opt)
23021 { # -sysroot "/" option
23022 # default target: /usr/lib, /usr/include
23023 # search libs: /usr/lib and /lib
23024 if(not -e $SystemRoot."/usr/lib") {
23025 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
23026 }
23027 if(not -e $SystemRoot."/lib") {
23028 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
23029 }
23030 if(not -e $SystemRoot."/usr/include") {
23031 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
23032 }
23033 readSystemDescriptor("
23034 <name>
23035 $DumpSystem
23036 </name>
23037 <headers>
23038 $SystemRoot/usr/include
23039 </headers>
23040 <libs>
23041 $SystemRoot/usr/lib
23042 </libs>
23043 <search_libs>
23044 $SystemRoot/lib
23045 </search_libs>");
23046 }
23047 else {
23048 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
23049 }
23050 detect_default_paths("bin|gcc"); # to check symbols
23051 if($OStarget eq "windows")
23052 { # to run dumpbin.exe
23053 # and undname.exe
23054 check_win32_env();
23055 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023056 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023057 exit(0);
23058 }
23059 if($CmpSystems)
23060 { # --cmp-systems
23061 detect_default_paths("bin"); # to extract dumps
23062 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023063 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023064 exit(0);
23065 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023066 if($GenerateTemplate)
23067 {
23068 writeFile("VERSION.xml", $DescriptorTemplate."\n");
23069 printMsg("INFO", "XML-descriptor template ./VERSION.xml has been generated");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023070 exit(0);
23071 }
23072 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023073 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023074 }
23075 else
23076 { # validate library name
23077 if($TargetLibraryName=~/[\*\/\\]/) {
23078 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
23079 }
23080 }
23081 if(not $TargetLibraryFName) {
23082 $TargetLibraryFName = $TargetLibraryName;
23083 }
23084 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
23085 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
23086 }
23087 if($SymbolsListPath)
23088 {
23089 if(not -f $SymbolsListPath) {
23090 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
23091 }
23092 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
23093 $SymbolsList{$Interface} = 1;
23094 }
23095 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023096 if($SkipSymbolsListPath)
23097 {
23098 if(not -f $SkipSymbolsListPath) {
23099 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
23100 }
23101 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
23102 $SkipSymbolsList{$Interface} = 1;
23103 }
23104 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023105 if($SkipHeadersPath)
23106 {
23107 if(not -f $SkipHeadersPath) {
23108 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
23109 }
23110 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023111 { # register for both versions
23112 $SkipHeadersList{1}{$Path} = 1;
23113 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023114 my ($CPath, $Type) = classifyPath($Path);
23115 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023116 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023117 }
23118 }
23119 if($ParamNamesPath)
23120 {
23121 if(not -f $ParamNamesPath) {
23122 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
23123 }
23124 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
23125 {
23126 if($Line=~s/\A(\w+)\;//)
23127 {
23128 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023129 if($Line=~/;(\d+);/)
23130 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023131 while($Line=~s/(\d+);(\w+)//) {
23132 $AddIntParams{$Interface}{$1}=$2;
23133 }
23134 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023135 else
23136 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023137 my $Num = 0;
23138 foreach my $Name (split(/;/, $Line)) {
23139 $AddIntParams{$Interface}{$Num++}=$Name;
23140 }
23141 }
23142 }
23143 }
23144 }
23145 if($AppPath)
23146 {
23147 if(not -f $AppPath) {
23148 exitStatus("Access_Error", "can't access file \'$AppPath\'");
23149 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040023150 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023151 $SymbolsList_App{$Interface} = 1;
23152 }
23153 }
23154 if($DumpAPI)
23155 { # --dump-abi
23156 # make an API dump
23157 create_ABI_Dump();
23158 exit($COMPILE_ERRORS);
23159 }
23160 # default: compare APIs
23161 # -d1 <path>
23162 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023163 compareInit();
23164 if($JoinReport or $DoubleReport)
23165 {
23166 compareAPIs("Binary");
23167 compareAPIs("Source");
23168 }
23169 elsif($BinaryOnly) {
23170 compareAPIs("Binary");
23171 }
23172 elsif($SourceOnly) {
23173 compareAPIs("Source");
23174 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023175 exitReport();
23176}
23177
23178scenario();