blob: b7225ed8ac4eeef1b61d7f556a9cf8be5e18ff70 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04003# ABI Compliance Checker (ACC) 1.99.8
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004# A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005#
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006# Copyright (C) 2009-2010 The Linux Foundation
7# Copyright (C) 2009-2011 Institute for System Programming, RAS
8# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009# Copyright (C) 2011-2013 ROSA Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010#
11# Written by Andrey Ponomarenko
12#
13# PLATFORMS
14# =========
15# Linux, FreeBSD, Mac OS X, Haiku, MS Windows, Symbian
16#
17# REQUIREMENTS
18# ============
19# Linux
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040020# - G++ (3.0-4.7, recommended 4.5 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021# - GNU Binutils (readelf, c++filt, objdump)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022# - Perl 5 (5.8 or newer)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040024#
25# Mac OS X
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040026# - Xcode (g++, c++filt, otool, nm)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040027# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040028#
29# MS Windows
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040030# - MinGW (3.0-4.7, recommended 4.5 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040031# - MS Visual C++ (dumpbin, undname, cl)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040032# - Active Perl 5 (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040033# - Sigcheck v1.71 or newer
34# - Info-ZIP 3.0 (zip, unzip)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040035# - Ctags (5.8 or newer)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040036# - Add tool locations to the PATH environment variable
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040037# - Run vsvars32.bat (C:\Microsoft Visual Studio 9.0\Common7\Tools\)
38#
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040039# COMPATIBILITY
40# =============
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 Ponomarenkof442c172013-07-30 19:08:11 +040067my $TOOL_VERSION = "1.99.8";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040068my $ABI_DUMP_VERSION = "3.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040069my $OLDEST_SUPPORTED_VERSION = "1.18";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040070my $XML_REPORT_VERSION = "1.1";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040071my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040072my $OSgroup = get_OSgroup();
73my $ORIG_DIR = cwd();
74my $TMP_DIR = tempdir(CLEANUP=>1);
75
76# Internal modules
77my $MODULES_DIR = get_Modules();
78push(@INC, get_dirname($MODULES_DIR));
79# Rules DB
80my %RULES_PATH = (
81 "Binary" => $MODULES_DIR."/RulesBin.xml",
82 "Source" => $MODULES_DIR."/RulesSrc.xml");
83
84my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName, $GenerateTemplate,
85$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
86$CheckObjectsOnly_Opt, $AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
87%RelativeDirectory, $TargetLibraryFName, $TestDump, $CheckImpl, $LoggingPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040088%TargetVersion, $InfoMsg, $UseOldDumps, $CrossGcc, %OutputLogPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040089$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem,
90$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc,
91$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040092$SkipHeadersPath, $CppCompat, $LogMode, $StdOut, $ListAffected, $ReportFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040093$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040094$SourceReportPath, $UseXML, $Browse, $OpenReport, $SortDump, $DumpFormat,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040095$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040096$CheckInfo, $Quick, $AffectLimit, $AllAffected);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040097
98my $CmdName = get_filename($0);
99my %OS_LibExt = (
100 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400101 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400102 "macos"=>"dylib",
103 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400104 "symbian"=>"dso",
105 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400106 },
107 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400108 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400109 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400110 "symbian"=>"lib",
111 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400112 }
113);
114
115my %OS_Archive = (
116 "windows"=>"zip",
117 "default"=>"tar.gz"
118);
119
120my %ERROR_CODE = (
121 # Compatible verdict
122 "Compatible"=>0,
123 "Success"=>0,
124 # Incompatible verdict
125 "Incompatible"=>1,
126 # Undifferentiated error code
127 "Error"=>2,
128 # System command is not found
129 "Not_Found"=>3,
130 # Cannot access input files
131 "Access_Error"=>4,
132 # Cannot compile header files
133 "Cannot_Compile"=>5,
134 # Header compiled with errors
135 "Compile_Error"=>6,
136 # Invalid input ABI dump
137 "Invalid_Dump"=>7,
138 # Incompatible version of ABI dump
139 "Dump_Version"=>8,
140 # Cannot find a module
141 "Module_Error"=>9,
142 # Empty intersection between
143 # headers and shared objects
144 "Empty_Intersection"=>10,
145 # Empty set of symbols in headers
146 "Empty_Set"=>11
147);
148
149my %HomePage = (
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400150 "Wiki"=>"http://ispras.linuxbase.org/index.php/ABI_compliance_checker",
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400151 "Dev1"=>"https://github.com/lvc/abi-compliance-checker",
152 "Dev2"=>"http://forge.ispras.ru/projects/abi-compliance-checker"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400153);
154
155my $ShortUsage = "ABI Compliance Checker (ACC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400156A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400157Copyright (C) 2012 ROSA Laboratory
158License: GNU LGPL or GNU GPL
159
160Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400161Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400162
163OLD.xml and NEW.xml are XML-descriptors:
164
165 <version>
166 1.0
167 </version>
168
169 <headers>
170 /path/to/headers/
171 </headers>
172
173 <libs>
174 /path/to/libraries/
175 </libs>
176
177More info: $CmdName --help\n";
178
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400179if($#ARGV==-1)
180{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400181 printMsg("INFO", $ShortUsage);
182 exit(0);
183}
184
185foreach (2 .. $#ARGV)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400186{ # correct comma separated options
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400187 if($ARGV[$_-1] eq ",")
188 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400189 $ARGV[$_-2].=",".$ARGV[$_];
190 splice(@ARGV, $_-1, 2);
191 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400192 elsif($ARGV[$_-1]=~/,\Z/)
193 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400194 $ARGV[$_-1].=$ARGV[$_];
195 splice(@ARGV, $_, 1);
196 }
197 elsif($ARGV[$_]=~/\A,/
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400198 and $ARGV[$_] ne ",")
199 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400200 $ARGV[$_-1].=$ARGV[$_];
201 splice(@ARGV, $_, 1);
202 }
203}
204
205GetOptions("h|help!" => \$Help,
206 "i|info!" => \$InfoMsg,
207 "v|version!" => \$ShowVersion,
208 "dumpversion!" => \$DumpVersion,
209# general options
210 "l|lib|library=s" => \$TargetLibraryName,
211 "d1|old|o=s" => \$Descriptor{1}{"Path"},
212 "d2|new|n=s" => \$Descriptor{2}{"Path"},
213 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
214 "old-dumps!" => \$UseOldDumps,
215# extra options
216 "d|descriptor-template!" => \$GenerateTemplate,
217 "app|application=s" => \$AppPath,
218 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +0400219 "cross-gcc|gcc-path=s" => \$CrossGcc,
220 "cross-prefix|gcc-prefix=s" => \$CrossPrefix,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400221 "sysroot=s" => \$SystemRoot_Opt,
222 "v1|version1|vnum=s" => \$TargetVersion{1},
223 "v2|version2=s" => \$TargetVersion{2},
224 "s|strict!" => \$StrictCompat,
225 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400226 "skip-symbols=s" => \$SkipSymbolsListPath,
227 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400228 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400229 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400230 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
231 "objects-only!" => \$CheckObjectsOnly_Opt,
232 "check-impl|check-implementation!" => \$CheckImpl,
233 "show-retval!" => \$ShowRetVal,
234 "use-dumps!" => \$UseDumps,
235 "nostdinc!" => \$NoStdInc,
236 "dump-system=s" => \$DumpSystem,
237 "sysinfo=s" => \$TargetSysInfo,
238 "cmp-systems!" => \$CmpSystems,
239 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400240 "ext|extended!" => \$ExtendedCheck,
241 "q|quiet!" => \$Quiet,
242 "stdout!" => \$StdOut,
243 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400244 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400245 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400246 "lang=s" => \$UserLang,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400247 "binary|bin|abi!" => \$BinaryOnly,
248 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400249 "affected-limit=s" => \$AffectLimit,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400250# other options
251 "test!" => \$TestTool,
252 "test-dump!" => \$TestDump,
253 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400254 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400255 "p|params=s" => \$ParamNamesPath,
256 "relpath1|relpath=s" => \$RelativeDirectory{1},
257 "relpath2=s" => \$RelativeDirectory{2},
258 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400259 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400260 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400261 "bin-report-path=s" => \$BinaryReportPath,
262 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400263 "log-path=s" => \$LoggingPath,
264 "log1-path=s" => \$OutputLogPath{1},
265 "log2-path=s" => \$OutputLogPath{2},
266 "logging-mode=s" => \$LogMode,
267 "list-affected!" => \$ListAffected,
268 "l-full|lib-full=s" => \$TargetLibraryFName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400269 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400270 "b|browse=s" => \$Browse,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400271 "open!" => \$OpenReport,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400272 "extra-info=s" => \$ExtraInfo,
273 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400274 "force!" => \$Force,
275 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400276 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400277 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400278 "quick!" => \$Quick,
279 "all-affected!" => \$AllAffected
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400280) or ERR_MESSAGE();
281
282sub ERR_MESSAGE()
283{
284 printMsg("INFO", "\n".$ShortUsage);
285 exit($ERROR_CODE{"Error"});
286}
287
288my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
289my $SLIB_TYPE = $LIB_TYPE;
290if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
291{ # show as "shared" library
292 $SLIB_TYPE = "shared";
293}
294my $LIB_EXT = getLIB_EXT($OSgroup);
295my $AR_EXT = getAR_EXT($OSgroup);
296my $BYTE_SIZE = 8;
297my $COMMON_LOG_PATH = "logs/run.log";
298
299my $HelpMessage="
300NAME:
301 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400302 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400303
304DESCRIPTION:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400305 ABI Compliance Checker (ACC) is a tool for checking backward binary and
306 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
307 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
308 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
309 and/or source-level compatibility: changes in calling stack, v-table changes,
310 removed symbols, renamed fields, etc. Binary incompatibility may result in
311 crashing or incorrect behavior of applications built with an old version of
312 a library if they run on a new one. Source incompatibility may result in
313 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400314
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400315 The tool is intended for developers of software libraries and maintainers
316 of operating systems who are interested in ensuring backward compatibility,
317 i.e. allow old applications to run or to be recompiled with newer library
318 versions.
319
320 Also the tool can be used by ISVs for checking applications portability to
321 new library versions. Found issues can be taken into account when adapting
322 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400323
324 This tool is free software: you can redistribute it and/or modify it
325 under the terms of the GNU LGPL or GNU GPL.
326
327USAGE:
328 $CmdName [options]
329
330EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400331 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400332
333 OLD.xml and NEW.xml are XML-descriptors:
334
335 <version>
336 1.0
337 </version>
338
339 <headers>
340 /path1/to/header(s)/
341 /path2/to/header(s)/
342 ...
343 </headers>
344
345 <libs>
346 /path1/to/library(ies)/
347 /path2/to/library(ies)/
348 ...
349 </libs>
350
351INFORMATION OPTIONS:
352 -h|-help
353 Print this help.
354
355 -i|-info
356 Print complete info.
357
358 -v|-version
359 Print version information.
360
361 -dumpversion
362 Print the tool version ($TOOL_VERSION) and don't do anything else.
363
364GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400365 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400366 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400367
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400368 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400369 Descriptor of 1st (old) library version.
370 It may be one of the following:
371
372 1. XML-descriptor (VERSION.xml file):
373
374 <version>
375 1.0
376 </version>
377
378 <headers>
379 /path1/to/header(s)/
380 /path2/to/header(s)/
381 ...
382 </headers>
383
384 <libs>
385 /path1/to/library(ies)/
386 /path2/to/library(ies)/
387 ...
388 </libs>
389
390 ... (XML-descriptor template
391 can be generated by -d option)
392
393 2. ABI dump generated by -dump option
394 3. Directory with headers and/or $SLIB_TYPE libraries
395 4. Single header file
396 5. Single $SLIB_TYPE library
397 6. Comma separated list of headers and/or libraries
398
399 If you are using an 2-6 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400400 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400401
402 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400403 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400404
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400405 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400406 Descriptor of 2nd (new) library version.
407
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400408 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400409 Create library ABI dump for the input XML descriptor. You can
410 transfer it anywhere and pass instead of the descriptor. Also
411 it can be used for debugging the tool.
412
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400413 Supported ABI dump versions: 2.0<=V<=$ABI_DUMP_VERSION
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400414
415 -old-dumps
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400416 Enable support for old-version ABI dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0).\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400417
418sub HELP_MESSAGE() {
419 printMsg("INFO", $HelpMessage."
420MORE INFO:
421 $CmdName --info\n");
422}
423
424sub INFO_MESSAGE()
425{
426 printMsg("INFO", "$HelpMessage
427EXTRA OPTIONS:
428 -d|-descriptor-template
429 Create XML-descriptor template ./VERSION.xml
430
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400431 -app|-application PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400432 This option allows to specify the application that should be checked
433 for portability to the new library version.
434
435 -static-libs
436 Check static libraries instead of the shared ones. The <libs> section
437 of the XML-descriptor should point to static libraries location.
438
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400439 -cross-gcc|-gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400440 Path to the cross GCC compiler to use instead of the usual (host) GCC.
441
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400442 -cross-prefix|-gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400443 GCC toolchain prefix.
444
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400445 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400446 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400447 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400448
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400449 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400450 Specify 1st library version outside the descriptor. This option is needed
451 if you have prefered an alternative descriptor type (see -d1 option).
452
453 In general case you should specify it in the XML-descriptor:
454 <version>
455 VERSION
456 </version>
457
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400458 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400459 Specify 2nd library version outside the descriptor.
460
461 -s|-strict
462 Treat all compatibility warnings as problems. Add a number of \"Low\"
463 severity problems to the return value of the tool.
464
465 -headers-only
466 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
467 provide a low quality compatibility report with false positives and
468 without detecting of added/removed symbols.
469
470 Alternatively you can write \"none\" word to the <libs> section
471 in the XML-descriptor:
472 <libs>
473 none
474 </libs>
475
476 -objects-only
477 Check $SLIB_TYPE libraries without header files. It is easy to run, but may
478 provide a low quality compatibility report with false positives and
479 without analysis of changes in parameters and data types.
480
481 Alternatively you can write \"none\" word to the <headers> section
482 in the XML-descriptor:
483 <headers>
484 none
485 </headers>
486
487 -check-impl|-check-implementation
488 Compare canonified disassembled binary code of $SLIB_TYPE libraries to
489 detect changes in the implementation. Add \'Problems with Implementation\'
490 section to the report.
491
492 -show-retval
493 Show the symbol's return type in the report.
494
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400495 -symbols-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400496 This option allows to specify a file with a list of symbols (mangled
497 names in C++) that should be checked, other symbols will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400498
499 -skip-symbols PATH
500 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400501
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400502 -headers-list PATH
503 The file with a list of headers, that should be checked/dumped.
504
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400505 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400506 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400507
508 -header NAME
509 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400510
511 -use-dumps
512 Make dumps for two versions of a library and compare dumps. This should
513 increase the performance of the tool and decrease the system memory usage.
514
515 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400516 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400517
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400518 -dump-system NAME -sysroot DIR
519 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400520 create XML descriptors and make ABI dumps for each library. The result
521 set of ABI dumps can be compared (--cmp-systems) with the other one
522 created for other version of operating system in order to check them for
523 compatibility. Do not forget to specify -cross-gcc option if your target
524 system requires some specific version of GCC compiler (different from
525 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400526 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400527
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400528 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400529 The same as the previous option but takes an XML descriptor of the target
530 system as input, where you should describe it:
531
532 /* Primary sections */
533
534 <name>
535 /* Name of the system */
536 </name>
537
538 <headers>
539 /* The list of paths to header files and/or
540 directories with header files, one per line */
541 </headers>
542
543 <libs>
544 /* The list of paths to shared libraries and/or
545 directories with shared libraries, one per line */
546 </libs>
547
548 /* Optional sections */
549
550 <search_headers>
551 /* List of directories to be searched
552 for header files to automatically
553 generate include paths, one per line */
554 </search_headers>
555
556 <search_libs>
557 /* List of directories to be searched
558 for shared libraries to resolve
559 dependencies, one per line */
560 </search_libs>
561
562 <tools>
563 /* List of directories with tools used
564 for analysis (GCC toolchain), one per line */
565 </tools>
566
567 <cross_prefix>
568 /* GCC toolchain prefix.
569 Examples:
570 arm-linux-gnueabi
571 arm-none-symbianelf */
572 </cross_prefix>
573
574 <gcc_options>
575 /* Additional GCC options, one per line */
576 </gcc_options>
577
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400578 -sysinfo DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400579 This option may be used with -dump-system to dump ABI of operating
580 systems and configure the dumping process.
581 Default:
582 modules/Targets/{unix, symbian, windows}
583
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400584 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400585 Compare two system ABI dumps. Create compatibility reports for each
586 library and the common HTML report including the summary of test
587 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400588 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400589
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400590 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400591 The file with a list of libraries, that should be dumped by
592 the -dump-system option or should be checked by the -cmp-systems option.
593
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400594 -ext|-extended
595 If your library A is supposed to be used by other library B and you
596 want to control the ABI of B, then you should enable this option. The
597 tool will check for changes in all data types, even if they are not
598 used by any function in the library A. Such data types are not part
599 of the A library ABI, but may be a part of the ABI of the B library.
600
601 The short scheme is:
602 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
603
604 -q|-quiet
605 Print all messages to the file instead of stdout and stderr.
606 Default path (can be changed by -log-path option):
607 $COMMON_LOG_PATH
608
609 -stdout
610 Print analysis results (compatibility reports and ABI dumps) to stdout
611 instead of creating a file. This would allow piping data to other programs.
612
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400613 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400614 Change format of compatibility report.
615 Formats:
616 htm - HTML format (default)
617 xml - XML format
618
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400619 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400620 Change format of ABI dump.
621 Formats:
622 perl - Data::Dumper format (default)
623 xml - XML format
624
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400625 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400626 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400627
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400628 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400629 Set library language (C or C++). You can use this option if the tool
630 cannot auto-detect a language. This option may be useful for checking
631 C-library headers (--lang=C) in --headers-only or --extended modes.
632
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400633 -binary|-bin|-abi
634 Show \"Binary\" compatibility problems only.
635 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400636 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400637
638 -source|-src|-api
639 Show \"Source\" compatibility problems only.
640 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400641 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400642
643 -affected-limit LIMIT
644 The maximum number of affected symbols listed under the description
645 of the changed type in the report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400646
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400647OTHER OPTIONS:
648 -test
649 Run internal tests. Create two binary incompatible versions of a sample
650 library and run the tool to check them for compatibility. This option
651 allows to check if the tool works correctly in the current environment.
652
653 -test-dump
654 Test ability to create, read and compare ABI dumps.
655
656 -debug
657 Debugging mode. Print debug info on the screen. Save intermediate
658 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400659 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400660
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400661 Also consider using --dump option for debugging the tool.
662
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400663 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400664 If your header files are written in C language and can be compiled
665 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
666 the tool about this and speedup the analysis.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400667
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400668 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400669 Path to file with the function parameter names. It can be used
670 for improving report view if the library header files have no
671 parameter names. File format:
672
673 func1;param1;param2;param3 ...
674 func2;param1;param2;param3 ...
675 ...
676
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400677 -relpath PATH
678 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400679 for dumping the library ABI (see -dump option).
680
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400681 -relpath1 PATH
682 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400683
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400684 -relpath2 PATH
685 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400686
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400687 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400688 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400689 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400691
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400692 -sort
693 Enable sorting of data in ABI dumps.
694
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400695 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400696 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400697 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400698 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400699
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400700 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400701 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400702 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400703 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400704
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400705 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400706 Path to \"Source\" compatibility report.
707 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400708 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400709
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400710 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400711 Log path for all messages.
712 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400713 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400714
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400715 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400716 Log path for 1st version of a library.
717 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400718 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400719
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400720 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400721 Log path for 2nd version of a library.
722 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400723 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400724
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400725 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400726 Change logging mode.
727 Modes:
728 w - overwrite old logs (default)
729 a - append old logs
730 n - do not write any logs
731
732 -list-affected
733 Generate file with the list of incompatible
734 symbols beside the HTML compatibility report.
735 Use 'c++filt \@file' command from GNU binutils
736 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400737 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400738 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400739 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400740
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400741 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400742 The component name in the title and summary of the HTML report.
743 Default:
744 library
745
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400746 -l-full|-lib-full NAME
747 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400748 will be displayed a name specified by -l option.
749
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400750 -b|-browse PROGRAM
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400751 Open report(s) in the browser (firefox, opera, etc.).
752
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400753 -open
754 Open report(s) in the default browser.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400755
756 -extra-info DIR
757 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400758
759 -extra-dump
760 Create extended ABI dump containing all symbols
761 from the translation unit.
762
763 -force
764 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400765
766 -tolerance LEVEL
767 Apply a set of heuristics to successfully compile input
768 header files. You can enable several tolerance levels by
769 joining them into one string (e.g. 13, 124, etc.).
770 Levels:
771 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
772 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
773 3 - skip headers that iclude non-Linux headers
774 4 - skip headers included by others
775
776 -tolerant
777 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400778
779 -check
780 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400781
782 -quick
783 Quick analysis. Disable check of some template instances.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400784
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400785REPORT:
786 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400787 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400788
789 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400790 logs/LIB_NAME/V1/log.txt
791 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400792
793EXIT CODES:
794 0 - Compatible. The tool has run without any errors.
795 non-zero - Incompatible or the tool has run with errors.
796
797REPORT BUGS TO:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400798 Andrey Ponomarenko <aponomarenko\@rosalab.ru>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400799
800MORE INFORMATION:
801 ".$HomePage{"Wiki"}."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400802 ".$HomePage{"Dev1"}."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400803}
804
805my $DescriptorTemplate = "
806<?xml version=\"1.0\" encoding=\"utf-8\"?>
807<descriptor>
808
809/* Primary sections */
810
811<version>
812 /* Version of the library */
813</version>
814
815<headers>
816 /* The list of paths to header files and/or
817 directories with header files, one per line */
818</headers>
819
820<libs>
821 /* The list of paths to shared libraries (*.$LIB_EXT) and/or
822 directories with shared libraries, one per line */
823</libs>
824
825/* Optional sections */
826
827<include_paths>
828 /* The list of include paths that will be provided
829 to GCC to compile library headers, one per line.
830 NOTE: If you define this section then the tool
831 will not automatically generate include paths */
832</include_paths>
833
834<add_include_paths>
835 /* The list of include paths that will be added
836 to the automatically generated include paths, one per line */
837</add_include_paths>
838
839<skip_include_paths>
840 /* The list of include paths that will be removed from the
841 list of automatically generated include paths, one per line */
842</skip_include_paths>
843
844<gcc_options>
845 /* Additional GCC options, one per line */
846</gcc_options>
847
848<include_preamble>
849 /* The list of header files that will be
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +0400850 included before other headers, one per line */
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400851</include_preamble>
852
853<defines>
854 /* The list of defines that will be added at the
855 headers compiling stage, one per line:
856 #define A B
857 #define C D */
858</defines>
859
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +0400860<add_namespaces>
861 /* The list of namespaces that should be added to the alanysis
862 if the tool cannot find them automatically, one per line */
863</add_namespaces>
864
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400865<skip_types>
866 /* The list of data types, that
867 should not be checked, one per line */
868</skip_types>
869
870<skip_symbols>
871 /* The list of functions (mangled/symbol names in C++),
872 that should not be checked, one per line */
873</skip_symbols>
874
875<skip_namespaces>
876 /* The list of C++ namespaces, that
877 should not be checked, one per line */
878</skip_namespaces>
879
880<skip_constants>
881 /* The list of constants that should
882 not be checked, one name per line */
883</skip_constants>
884
885<skip_headers>
886 /* The list of header files and/or directories
887 with header files that should not be checked, one per line */
888</skip_headers>
889
890<skip_libs>
891 /* The list of shared libraries and/or directories
892 with shared libraries that should not be checked, one per line */
893</skip_libs>
894
895<skip_including>
896 /* The list of header files, that cannot be included
897 directly (or non-self compiled ones), one per line */
898</skip_including>
899
900<search_headers>
901 /* List of directories to be searched
902 for header files to automatically
903 generate include paths, one per line. */
904</search_headers>
905
906<search_libs>
907 /* List of directories to be searched
908 for shared librariess to resolve
909 dependencies, one per line */
910</search_libs>
911
912<tools>
913 /* List of directories with tools used
914 for analysis (GCC toolchain), one per line */
915</tools>
916
917<cross_prefix>
918 /* GCC toolchain prefix.
919 Examples:
920 arm-linux-gnueabi
921 arm-none-symbianelf */
922</cross_prefix>
923
924</descriptor>";
925
926my %Operator_Indication = (
927 "not" => "~",
928 "assign" => "=",
929 "andassign" => "&=",
930 "orassign" => "|=",
931 "xorassign" => "^=",
932 "or" => "|",
933 "xor" => "^",
934 "addr" => "&",
935 "and" => "&",
936 "lnot" => "!",
937 "eq" => "==",
938 "ne" => "!=",
939 "lt" => "<",
940 "lshift" => "<<",
941 "lshiftassign" => "<<=",
942 "rshiftassign" => ">>=",
943 "call" => "()",
944 "mod" => "%",
945 "modassign" => "%=",
946 "subs" => "[]",
947 "land" => "&&",
948 "lor" => "||",
949 "rshift" => ">>",
950 "ref" => "->",
951 "le" => "<=",
952 "deref" => "*",
953 "mult" => "*",
954 "preinc" => "++",
955 "delete" => " delete",
956 "vecnew" => " new[]",
957 "vecdelete" => " delete[]",
958 "predec" => "--",
959 "postinc" => "++",
960 "postdec" => "--",
961 "plusassign" => "+=",
962 "plus" => "+",
963 "minus" => "-",
964 "minusassign" => "-=",
965 "gt" => ">",
966 "ge" => ">=",
967 "new" => " new",
968 "multassign" => "*=",
969 "divassign" => "/=",
970 "div" => "/",
971 "neg" => "-",
972 "pos" => "+",
973 "memref" => "->*",
974 "compound" => "," );
975
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400976my %UnknownOperator;
977
978my %NodeType= (
979 "array_type" => "Array",
980 "binfo" => "Other",
981 "boolean_type" => "Intrinsic",
982 "complex_type" => "Intrinsic",
983 "const_decl" => "Other",
984 "enumeral_type" => "Enum",
985 "field_decl" => "Other",
986 "function_decl" => "Other",
987 "function_type" => "FunctionType",
988 "identifier_node" => "Other",
989 "integer_cst" => "Other",
990 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400991 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400992 "method_type" => "MethodType",
993 "namespace_decl" => "Other",
994 "parm_decl" => "Other",
995 "pointer_type" => "Pointer",
996 "real_cst" => "Other",
997 "real_type" => "Intrinsic",
998 "record_type" => "Struct",
999 "reference_type" => "Ref",
1000 "string_cst" => "Other",
1001 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001002 "template_type_parm" => "TemplateParam",
1003 "typename_type" => "TypeName",
1004 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001005 "tree_list" => "Other",
1006 "tree_vec" => "Other",
1007 "type_decl" => "Other",
1008 "union_type" => "Union",
1009 "var_decl" => "Other",
1010 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001011 "nop_expr" => "Other", #
1012 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001013 "offset_type" => "Other" );
1014
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001015my %CppKeywords_C = map {$_=>1} (
1016 # C++ 2003 keywords
1017 "public",
1018 "protected",
1019 "private",
1020 "default",
1021 "template",
1022 "new",
1023 #"asm",
1024 "dynamic_cast",
1025 "auto",
1026 "try",
1027 "namespace",
1028 "typename",
1029 "using",
1030 "reinterpret_cast",
1031 "friend",
1032 "class",
1033 "virtual",
1034 "const_cast",
1035 "mutable",
1036 "static_cast",
1037 "export",
1038 # C++0x keywords
1039 "noexcept",
1040 "nullptr",
1041 "constexpr",
1042 "static_assert",
1043 "explicit",
1044 # cannot be used as a macro name
1045 # as it is an operator in C++
1046 "and",
1047 #"and_eq",
1048 "not",
1049 #"not_eq",
1050 "or"
1051 #"or_eq",
1052 #"bitand",
1053 #"bitor",
1054 #"xor",
1055 #"xor_eq",
1056 #"compl"
1057);
1058
1059my %CppKeywords_F = map {$_=>1} (
1060 "delete",
1061 "catch",
1062 "alignof",
1063 "thread_local",
1064 "decltype",
1065 "typeid"
1066);
1067
1068my %CppKeywords_O = map {$_=>1} (
1069 "bool",
1070 "register",
1071 "inline",
1072 "operator"
1073);
1074
1075my %CppKeywords_A = map {$_=>1} (
1076 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001077 "throw",
1078 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001079);
1080
1081foreach (keys(%CppKeywords_C),
1082keys(%CppKeywords_F),
1083keys(%CppKeywords_O)) {
1084 $CppKeywords_A{$_}=1;
1085}
1086
1087# Header file extensions as described by gcc
1088my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
1089
1090my %IntrinsicMangling = (
1091 "void" => "v",
1092 "bool" => "b",
1093 "wchar_t" => "w",
1094 "char" => "c",
1095 "signed char" => "a",
1096 "unsigned char" => "h",
1097 "short" => "s",
1098 "unsigned short" => "t",
1099 "int" => "i",
1100 "unsigned int" => "j",
1101 "long" => "l",
1102 "unsigned long" => "m",
1103 "long long" => "x",
1104 "__int64" => "x",
1105 "unsigned long long" => "y",
1106 "__int128" => "n",
1107 "unsigned __int128" => "o",
1108 "float" => "f",
1109 "double" => "d",
1110 "long double" => "e",
1111 "__float80" => "e",
1112 "__float128" => "g",
1113 "..." => "z"
1114);
1115
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001116my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
1117
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001118my %StdcxxMangling = (
1119 "3std"=>"St",
1120 "3std9allocator"=>"Sa",
1121 "3std12basic_string"=>"Sb",
1122 "3std12basic_stringIcE"=>"Ss",
1123 "3std13basic_istreamIcE"=>"Si",
1124 "3std13basic_ostreamIcE"=>"So",
1125 "3std14basic_iostreamIcE"=>"Sd"
1126);
1127
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001128my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001129my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1130
1131my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001132my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001133
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001134my %ConstantSuffix = (
1135 "unsigned int"=>"u",
1136 "long"=>"l",
1137 "unsigned long"=>"ul",
1138 "long long"=>"ll",
1139 "unsigned long long"=>"ull"
1140);
1141
1142my %ConstantSuffixR =
1143reverse(%ConstantSuffix);
1144
1145my %OperatorMangling = (
1146 "~" => "co",
1147 "=" => "aS",
1148 "|" => "or",
1149 "^" => "eo",
1150 "&" => "an",#ad (addr)
1151 "==" => "eq",
1152 "!" => "nt",
1153 "!=" => "ne",
1154 "<" => "lt",
1155 "<=" => "le",
1156 "<<" => "ls",
1157 "<<=" => "lS",
1158 ">" => "gt",
1159 ">=" => "ge",
1160 ">>" => "rs",
1161 ">>=" => "rS",
1162 "()" => "cl",
1163 "%" => "rm",
1164 "[]" => "ix",
1165 "&&" => "aa",
1166 "||" => "oo",
1167 "*" => "ml",#de (deref)
1168 "++" => "pp",#
1169 "--" => "mm",#
1170 "new" => "nw",
1171 "delete" => "dl",
1172 "new[]" => "na",
1173 "delete[]" => "da",
1174 "+=" => "pL",
1175 "+" => "pl",#ps (pos)
1176 "-" => "mi",#ng (neg)
1177 "-=" => "mI",
1178 "*=" => "mL",
1179 "/=" => "dV",
1180 "&=" => "aN",
1181 "|=" => "oR",
1182 "%=" => "rM",
1183 "^=" => "eO",
1184 "/" => "dv",
1185 "->*" => "pm",
1186 "->" => "pt",#rf (ref)
1187 "," => "cm",
1188 "?" => "qu",
1189 "." => "dt",
1190 "sizeof"=> "sz"#st
1191);
1192
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001193my %Intrinsic_Keywords = map {$_=>1} (
1194 "true",
1195 "false",
1196 "_Bool",
1197 "_Complex",
1198 "const",
1199 "int",
1200 "long",
1201 "void",
1202 "short",
1203 "float",
1204 "volatile",
1205 "restrict",
1206 "unsigned",
1207 "signed",
1208 "char",
1209 "double",
1210 "class",
1211 "struct",
1212 "union",
1213 "enum"
1214);
1215
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001216my %GlibcHeader = map {$_=>1} (
1217 "aliases.h",
1218 "argp.h",
1219 "argz.h",
1220 "assert.h",
1221 "cpio.h",
1222 "ctype.h",
1223 "dirent.h",
1224 "envz.h",
1225 "errno.h",
1226 "error.h",
1227 "execinfo.h",
1228 "fcntl.h",
1229 "fstab.h",
1230 "ftw.h",
1231 "glob.h",
1232 "grp.h",
1233 "iconv.h",
1234 "ifaddrs.h",
1235 "inttypes.h",
1236 "langinfo.h",
1237 "limits.h",
1238 "link.h",
1239 "locale.h",
1240 "malloc.h",
1241 "math.h",
1242 "mntent.h",
1243 "monetary.h",
1244 "nl_types.h",
1245 "obstack.h",
1246 "printf.h",
1247 "pwd.h",
1248 "regex.h",
1249 "sched.h",
1250 "search.h",
1251 "setjmp.h",
1252 "shadow.h",
1253 "signal.h",
1254 "spawn.h",
1255 "stdarg.h",
1256 "stdint.h",
1257 "stdio.h",
1258 "stdlib.h",
1259 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001260 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001261 "tar.h",
1262 "termios.h",
1263 "time.h",
1264 "ulimit.h",
1265 "unistd.h",
1266 "utime.h",
1267 "wchar.h",
1268 "wctype.h",
1269 "wordexp.h" );
1270
1271my %GlibcDir = map {$_=>1} (
1272 "arpa",
1273 "bits",
1274 "gnu",
1275 "netinet",
1276 "net",
1277 "nfs",
1278 "rpc",
1279 "sys",
1280 "linux" );
1281
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001282my %WinHeaders = map {$_=>1} (
1283 "dos.h",
1284 "process.h",
1285 "winsock.h",
1286 "config-win.h",
1287 "mem.h",
1288 "windows.h",
1289 "winsock2.h",
1290 "crtdbg.h",
1291 "ws2tcpip.h"
1292);
1293
1294my %ObsoleteHeaders = map {$_=>1} (
1295 "iostream.h",
1296 "fstream.h"
1297);
1298
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001299my %AlienHeaders = map {$_=>1} (
1300 # Solaris
1301 "thread.h",
1302 "sys/atomic.h",
1303 # HPUX
1304 "sys/stream.h",
1305 # Symbian
1306 "AknDoc.h",
1307 # Atari ST
1308 "ext.h",
1309 "tos.h",
1310 # MS-DOS
1311 "alloc.h",
1312 # Sparc
1313 "sys/atomic.h"
1314);
1315
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001316my %ConfHeaders = map {$_=>1} (
1317 "atomic",
1318 "conf.h",
1319 "config.h",
1320 "configure.h",
1321 "build.h",
1322 "setup.h"
1323);
1324
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001325my %LocalIncludes = map {$_=>1} (
1326 "/usr/local/include",
1327 "/usr/local" );
1328
1329my %OS_AddPath=(
1330# These paths are needed if the tool cannot detect them automatically
1331 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001332 "include"=>[
1333 "/Library",
1334 "/Developer/usr/include"
1335 ],
1336 "lib"=>[
1337 "/Library",
1338 "/Developer/usr/lib"
1339 ],
1340 "bin"=>[
1341 "/Developer/usr/bin"
1342 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001343 },
1344 "beos"=>{
1345 # Haiku has GCC 2.95.3 by default
1346 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001347 "include"=>[
1348 "/boot/common",
1349 "/boot/develop"
1350 ],
1351 "lib"=>[
1352 "/boot/common/lib",
1353 "/boot/system/lib",
1354 "/boot/apps"
1355 ],
1356 "bin"=>[
1357 "/boot/common/bin",
1358 "/boot/system/bin",
1359 "/boot/develop/abi"
1360 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001362);
1363
1364my %Slash_Type=(
1365 "default"=>"/",
1366 "windows"=>"\\"
1367);
1368
1369my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1370
1371# Global Variables
1372my %COMMON_LANGUAGE=(
1373 1 => "C",
1374 2 => "C" );
1375
1376my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001377my $MAX_CPPFILT_FILE_SIZE = 50000;
1378my $CPPFILT_SUPPORT_FILE;
1379
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001380my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1381
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001382my $STDCXX_TESTING = 0;
1383my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001384my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001385
1386my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
1387my $CheckObjectsOnly = $CheckObjectsOnly_Opt;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001388
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001389my $TargetComponent;
1390
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001391my $CheckUndefined = 0;
1392
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001393# Set Target Component Name
1394if($TargetComponent_Opt) {
1395 $TargetComponent = lc($TargetComponent_Opt);
1396}
1397else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001398{ # default: library
1399 # other components: header, system, ...
1400 $TargetComponent = "library";
1401}
1402
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001403my $TOP_REF = "<a style='font-size:11px;' href='#Top'>to the top</a>";
1404
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001405my $SystemRoot;
1406
1407my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001408my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001409my %LOG_PATH;
1410my %DEBUG_PATH;
1411my %Cache;
1412my %LibInfo;
1413my $COMPILE_ERRORS = 0;
1414my %CompilerOptions;
1415my %CheckedDyLib;
1416my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1417
1418# Constants (#defines)
1419my %Constants;
1420my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001421my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001422
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001423# Extra Info
1424my %SymbolHeader;
1425my %KnownLibs;
1426
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001427# Templates
1428my %TemplateInstance;
1429my %BasicTemplate;
1430my %TemplateArg;
1431my %TemplateDecl;
1432my %TemplateMap;
1433
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001434# Types
1435my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001436my %SkipTypes = (
1437 "1"=>{},
1438 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001439my %CheckedTypes;
1440my %TName_Tid;
1441my %EnumMembName_Id;
1442my %NestedNameSpaces = (
1443 "1"=>{},
1444 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001445my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001446my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001447my %ClassVTable;
1448my %ClassVTable_Content;
1449my %VTableClass;
1450my %AllocableClass;
1451my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001452my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001453my %Class_SubClasses;
1454my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001455my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001456my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001457
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001458my %CheckedTypeInfo;
1459
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001460# Typedefs
1461my %Typedef_BaseName;
1462my %Typedef_Tr;
1463my %Typedef_Eq;
1464my %StdCxxTypedef;
1465my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001466my %MissedBase;
1467my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001468my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001469
1470# Symbols
1471my %SymbolInfo;
1472my %tr_name;
1473my %mangled_name_gcc;
1474my %mangled_name;
1475my %SkipSymbols = (
1476 "1"=>{},
1477 "2"=>{} );
1478my %SkipNameSpaces = (
1479 "1"=>{},
1480 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001481my %AddNameSpaces = (
1482 "1"=>{},
1483 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001484my %SymbolsList;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001485my %SkipSymbolsList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001486my %SymbolsList_App;
1487my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001488my %Symbol_Library = (
1489 "1"=>{},
1490 "2"=>{} );
1491my %Library_Symbol = (
1492 "1"=>{},
1493 "2"=>{} );
1494my %DepSymbol_Library = (
1495 "1"=>{},
1496 "2"=>{} );
1497my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001498 "1"=>{},
1499 "2"=>{} );
1500my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001501my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001502my %AddIntParams;
1503my %Interface_Impl;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001504my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001505my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001506my %Library_Needed= (
1507 "1"=>{},
1508 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001509
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001510# Extra Info
1511my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001512my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001513
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001514# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001515my %Include_Preamble = (
1516 "1"=>[],
1517 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001518my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001519my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001520my %HeaderName_Paths;
1521my %Header_Dependency;
1522my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001523my %Include_Paths = (
1524 "1"=>[],
1525 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001526my %INC_PATH_AUTODETECT = (
1527 "1"=>1,
1528 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001529my %Add_Include_Paths = (
1530 "1"=>[],
1531 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001532my %Skip_Include_Paths;
1533my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001534my %Header_ErrorRedirect;
1535my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001536my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001537my %Header_ShouldNotBeUsed;
1538my %RecursiveIncludes;
1539my %Header_Include_Prefix;
1540my %SkipHeaders;
1541my %SkipHeadersList=(
1542 "1"=>{},
1543 "2"=>{} );
1544my %SkipLibs;
1545my %Include_Order;
1546my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001547my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001548my %TUnit_Funcs;
1549my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001550
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001551my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001552 "1"=>0,
1553 "2"=>0 );
1554my %AutoPreambleMode = (
1555 "1"=>0,
1556 "2"=>0 );
1557my %MinGWMode = (
1558 "1"=>0,
1559 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001560my %Cpp0xMode = (
1561 "1"=>0,
1562 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001563
1564# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001565my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001566my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001567my %RegisteredSONAMEs;
1568my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001569
1570# System Objects
1571my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001572my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001573my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001574
1575# System Headers
1576my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001577my @DefaultCppPaths;
1578my @DefaultGccPaths;
1579my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001580my %DefaultCppHeader;
1581my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001582my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001583
1584# Merging
1585my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001586my $Version;
1587my %AddedInt;
1588my %RemovedInt;
1589my %AddedInt_Virt;
1590my %RemovedInt_Virt;
1591my %VirtualReplacement;
1592my %ChangedTypedef;
1593my %CompatRules;
1594my %IncompleteRules;
1595my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001596my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001597my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001598my %ReturnedClass;
1599my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001600my %SourceAlternative;
1601my %SourceAlternative_B;
1602my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001603my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001604
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001605# Calling Conventions
1606my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001607 1=>{ "R"=>0, "P"=>0 },
1608 2=>{ "R"=>0, "P"=>0 }
1609);
1610
1611# ABI Dump
1612my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001613
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001614# OS Compliance
1615my %TargetLibs;
1616my %TargetHeaders;
1617
1618# OS Specifics
1619my $OStarget = $OSgroup;
1620my %TargetTools;
1621
1622# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001623my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001624
1625# Recursion locks
1626my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001627my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001628my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001629my @RecurInclude;
1630my @RecurConstant;
1631
1632# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001633my %SystemPaths = (
1634 "include"=>[],
1635 "lib"=>[],
1636 "bin"=>[]
1637);
1638my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001639my $GCC_PATH;
1640
1641# Symbols versioning
1642my %SymVer = (
1643 "1"=>{},
1644 "2"=>{} );
1645
1646# Problem descriptions
1647my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001648my %CompatProblems_Constants;
1649my %CompatProblems_Impl;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001650my %TotalAffected;
1651
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001652# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001653my $ContentID = 1;
1654my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1655my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1656my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1657my $ContentSpanEnd = "</span>\n";
1658my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1659my $ContentDivEnd = "</div>\n";
1660my $Content_Counter = 0;
1661
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001662# Modes
1663my $JoinReport = 1;
1664my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001665
1666sub get_Modules()
1667{
1668 my $TOOL_DIR = get_dirname($0);
1669 if(not $TOOL_DIR)
1670 { # patch for MS Windows
1671 $TOOL_DIR = ".";
1672 }
1673 my @SEARCH_DIRS = (
1674 # tool's directory
1675 abs_path($TOOL_DIR),
1676 # relative path to modules
1677 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001678 # install path
1679 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001680 );
1681 foreach my $DIR (@SEARCH_DIRS)
1682 {
1683 if(not is_abs($DIR))
1684 { # relative path
1685 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1686 }
1687 if(-d $DIR."/modules") {
1688 return $DIR."/modules";
1689 }
1690 }
1691 exitStatus("Module_Error", "can't find modules");
1692}
1693
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001694my %LoadedModules = ();
1695
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001696sub loadModule($)
1697{
1698 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001699 if(defined $LoadedModules{$Name}) {
1700 return;
1701 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001702 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1703 if(not -f $Path) {
1704 exitStatus("Module_Error", "can't access \'$Path\'");
1705 }
1706 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001707 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001708}
1709
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001710sub readModule($$)
1711{
1712 my ($Module, $Name) = @_;
1713 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1714 if(not -f $Path) {
1715 exitStatus("Module_Error", "can't access \'$Path\'");
1716 }
1717 return readFile($Path);
1718}
1719
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001720sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001721{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001722 my $Number = $_[0];
1723 if(not $Number) {
1724 $Number = 1;
1725 }
1726 else {
1727 $Number = int($Number)+1;
1728 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001729 if($Number>3) {
1730 return $Number."th";
1731 }
1732 elsif($Number==1) {
1733 return "1st";
1734 }
1735 elsif($Number==2) {
1736 return "2nd";
1737 }
1738 elsif($Number==3) {
1739 return "3rd";
1740 }
1741 else {
1742 return $Number;
1743 }
1744}
1745
1746sub search_Tools($)
1747{
1748 my $Name = $_[0];
1749 return "" if(not $Name);
1750 if(my @Paths = keys(%TargetTools))
1751 {
1752 foreach my $Path (@Paths)
1753 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001754 if(-f join_P($Path, $Name)) {
1755 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001756 }
1757 if($CrossPrefix)
1758 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001759 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001760 if(-f $Candidate) {
1761 return $Candidate;
1762 }
1763 }
1764 }
1765 }
1766 else {
1767 return "";
1768 }
1769}
1770
1771sub synch_Cmd($)
1772{
1773 my $Name = $_[0];
1774 if(not $GCC_PATH)
1775 { # GCC was not found yet
1776 return "";
1777 }
1778 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001779 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001780 return $Candidate;
1781 }
1782 return "";
1783}
1784
1785sub get_CmdPath($)
1786{
1787 my $Name = $_[0];
1788 return "" if(not $Name);
1789 if(defined $Cache{"get_CmdPath"}{$Name}) {
1790 return $Cache{"get_CmdPath"}{$Name};
1791 }
1792 my %BinUtils = map {$_=>1} (
1793 "c++filt",
1794 "objdump",
1795 "readelf"
1796 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001797 if($BinUtils{$Name} and $GCC_PATH)
1798 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001799 if(my $Dir = get_dirname($GCC_PATH)) {
1800 $TargetTools{$Dir}=1;
1801 }
1802 }
1803 my $Path = search_Tools($Name);
1804 if(not $Path and $OSgroup eq "windows") {
1805 $Path = search_Tools($Name.".exe");
1806 }
1807 if(not $Path and $BinUtils{$Name})
1808 {
1809 if($CrossPrefix)
1810 { # user-defined prefix
1811 $Path = search_Cmd($CrossPrefix."-".$Name);
1812 }
1813 }
1814 if(not $Path and $BinUtils{$Name})
1815 {
1816 if(my $Candidate = synch_Cmd($Name))
1817 { # synch with GCC
1818 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001819 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001820 if(-f $Candidate) {
1821 $Path = $Candidate;
1822 }
1823 }
1824 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001825 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001826 $Path = $Candidate;
1827 }
1828 }
1829 }
1830 if(not $Path) {
1831 $Path = search_Cmd($Name);
1832 }
1833 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001834 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001835 $Path=search_Cmd($Name.".exe");
1836 }
1837 if($Path=~/\s/) {
1838 $Path = "\"".$Path."\"";
1839 }
1840 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1841}
1842
1843sub search_Cmd($)
1844{
1845 my $Name = $_[0];
1846 return "" if(not $Name);
1847 if(defined $Cache{"search_Cmd"}{$Name}) {
1848 return $Cache{"search_Cmd"}{$Name};
1849 }
1850 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1851 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1852 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001853 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001854 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001855 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001856 if(-f $CmdPath)
1857 {
1858 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001859 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001860 }
1861 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1862 }
1863 }
1864 return ($Cache{"search_Cmd"}{$Name} = "");
1865}
1866
1867sub get_CmdPath_Default($)
1868{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001869 return "" if(not $_[0]);
1870 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1871 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001872 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001873 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1874}
1875
1876sub get_CmdPath_Default_I($)
1877{ # search in PATH
1878 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001879 if($Name=~/find/)
1880 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001881 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001882 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001883 }
1884 }
1885 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001886 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001887 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001888 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001889 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001890 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001891 if($OSgroup eq "windows")
1892 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001893 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001894 return $Name;
1895 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001896 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001897 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001898 {
1899 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001900 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001901 }
1902 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001903 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001904}
1905
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001906sub classifyPath($)
1907{
1908 my $Path = $_[0];
1909 if($Path=~/[\*\[]/)
1910 { # wildcard
1911 $Path=~s/\*/.*/g;
1912 $Path=~s/\\/\\\\/g;
1913 return ($Path, "Pattern");
1914 }
1915 elsif($Path=~/[\/\\]/)
1916 { # directory or relative path
1917 return (path_format($Path, $OSgroup), "Path");
1918 }
1919 else {
1920 return ($Path, "Name");
1921 }
1922}
1923
1924sub readDescriptor($$)
1925{
1926 my ($LibVersion, $Content) = @_;
1927 return if(not $LibVersion);
1928 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1929 if(not $Content) {
1930 exitStatus("Error", "$DName is empty");
1931 }
1932 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001933 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001934 }
1935 $Content=~s/\/\*(.|\n)+?\*\///g;
1936 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001937
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001938 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1939 if($TargetVersion{$LibVersion}) {
1940 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1941 }
1942 if(not $Descriptor{$LibVersion}{"Version"}) {
1943 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1944 }
1945 if($Content=~/{RELPATH}/)
1946 {
1947 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1948 $Content =~ s/{RELPATH}/$RelDir/g;
1949 }
1950 else
1951 {
1952 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1953 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1954 }
1955 }
1956
1957 if(not $CheckObjectsOnly_Opt)
1958 {
1959 my $DHeaders = parseTag(\$Content, "headers");
1960 if(not $DHeaders) {
1961 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1962 }
1963 elsif(lc($DHeaders) ne "none")
1964 { # append the descriptor headers list
1965 if($Descriptor{$LibVersion}{"Headers"})
1966 { # multiple descriptors
1967 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
1968 }
1969 else {
1970 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1971 }
1972 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1973 {
1974 if(not -e $Path) {
1975 exitStatus("Access_Error", "can't access \'$Path\'");
1976 }
1977 }
1978 }
1979 }
1980 if(not $CheckHeadersOnly_Opt)
1981 {
1982 my $DObjects = parseTag(\$Content, "libs");
1983 if(not $DObjects) {
1984 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1985 }
1986 elsif(lc($DObjects) ne "none")
1987 { # append the descriptor libraries list
1988 if($Descriptor{$LibVersion}{"Libs"})
1989 { # multiple descriptors
1990 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1991 }
1992 else {
1993 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1994 }
1995 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1996 {
1997 if(not -e $Path) {
1998 exitStatus("Access_Error", "can't access \'$Path\'");
1999 }
2000 }
2001 }
2002 }
2003 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
2004 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002005 if(not -d $Path) {
2006 exitStatus("Access_Error", "can't access directory \'$Path\'");
2007 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002008 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002009 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002010 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002011 }
2012 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
2013 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002014 if(not -d $Path) {
2015 exitStatus("Access_Error", "can't access directory \'$Path\'");
2016 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002017 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002018 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002019 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002020 }
2021 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
2022 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002023 if(not -d $Path) {
2024 exitStatus("Access_Error", "can't access directory \'$Path\'");
2025 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002026 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002027 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002028 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002029 $TargetTools{$Path}=1;
2030 }
2031 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
2032 $CrossPrefix = $Prefix;
2033 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002034 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002035 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
2036 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002037 if(not -d $Path) {
2038 exitStatus("Access_Error", "can't access directory \'$Path\'");
2039 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002040 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002041 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002042 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002043 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002044 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002045 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
2046 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002047 if(not -d $Path) {
2048 exitStatus("Access_Error", "can't access directory \'$Path\'");
2049 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002050 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002051 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002052 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002053 }
2054 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002055 { # skip some auto-generated include paths
2056 if(not is_abs($Path))
2057 {
2058 if(my $P = abs_path($Path)) {
2059 $Path = $P;
2060 }
2061 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002062 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002063 }
2064 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002065 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002066 my ($CPath, $Type) = classifyPath($Path);
2067 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002068 }
2069 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002070 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
2071 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002072 if($Option!~/\A\-(Wl|l|L)/)
2073 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002074 $CompilerOptions{$LibVersion} .= " ".$Option;
2075 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002076 }
2077 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
2078 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
2079 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002080 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002081 my ($CPath, $Type) = classifyPath($Path);
2082 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002083 }
2084 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
2085 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
2086 {
2087 my ($CPath, $Type) = classifyPath($Path);
2088 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
2089 }
2090 if(my $DDefines = parseTag(\$Content, "defines"))
2091 {
2092 if($Descriptor{$LibVersion}{"Defines"})
2093 { # multiple descriptors
2094 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
2095 }
2096 else {
2097 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
2098 }
2099 }
2100 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2101 {
2102 if($Order=~/\A(.+):(.+)\Z/) {
2103 $Include_Order{$LibVersion}{$1} = $2;
2104 }
2105 }
2106 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2107 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002108 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002109 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2110 }
2111 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2112 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002113 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002114 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2115 }
2116 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2117 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2118 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002119 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2120 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2121 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002122 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2123 $SkipConstants{$LibVersion}{$Constant} = 1;
2124 }
2125 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2126 {
2127 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002128 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002129 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2130 }
2131 else {
2132 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2133 }
2134 }
2135}
2136
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002137sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002138{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002139 my $CodeRef = shift(@_);
2140 my $Tag = shift(@_);
2141 if(not $Tag or not $CodeRef) {
2142 return undef;
2143 }
2144 my $Sp = 0;
2145 if(@_) {
2146 $Sp = shift(@_);
2147 }
2148 my $Start = index(${$CodeRef}, "<$Tag>");
2149 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002150 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002151 my $End = index(${$CodeRef}, "</$Tag>");
2152 if($End!=-1)
2153 {
2154 my $TS = length($Tag)+3;
2155 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2156 substr($Content, 0, $TS-1, ""); # cut start tag
2157 substr($Content, -$TS, $TS, ""); # cut end tag
2158 if(not $Sp)
2159 {
2160 $Content=~s/\A\s+//g;
2161 $Content=~s/\s+\Z//g;
2162 }
2163 if(substr($Content, 0, 1) ne "<") {
2164 $Content = xmlSpecChars_R($Content);
2165 }
2166 return $Content;
2167 }
2168 }
2169 return undef;
2170}
2171
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002172sub getInfo($)
2173{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002174 my $DumpPath = $_[0];
2175 return if(not $DumpPath or not -f $DumpPath);
2176
2177 readTUDump($DumpPath);
2178
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002179 # processing info
2180 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002181
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002182 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002183 setAnonTypedef_All();
2184 }
2185
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002186 getTypeInfo_All();
2187 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002188 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002189 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002190 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002191
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002192 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002193 %LibInfo = ();
2194 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002195 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002196 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002197 %TemplateDecl = ();
2198 %StdCxxTypedef = ();
2199 %MissedTypedef = ();
2200 %Typedef_Tr = ();
2201 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002202 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002203
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002204 # clean cache
2205 delete($Cache{"getTypeAttr"});
2206 delete($Cache{"getTypeDeclId"});
2207
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002208 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002209 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002210 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002211 }
2212 else
2213 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002214 if($BinaryOnly and not $ExtendedCheck)
2215 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002216 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002217 }
2218 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002219 remove_Unused($Version, "Extended");
2220 }
2221 }
2222
2223 if($CheckInfo)
2224 {
2225 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2226 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2227 }
2228
2229 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2230 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002231 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002232 }
2233
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002234 if($Debug) {
2235 # debugMangling($Version);
2236 }
2237}
2238
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002239sub readTUDump($)
2240{
2241 my $DumpPath = $_[0];
2242
2243 open(TU_DUMP, $DumpPath);
2244 local $/ = undef;
2245 my $Content = <TU_DUMP>;
2246 close(TU_DUMP);
2247
2248 unlink($DumpPath);
2249
2250 $Content=~s/\n[ ]+/ /g;
2251 my @Lines = split("\n", $Content);
2252
2253 # clean memory
2254 undef $Content;
2255
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002256 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002257
2258 foreach (0 .. $#Lines)
2259 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002260 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002261 { # get a number and attributes of a node
2262 next if(not $NodeType{$2});
2263 $LibInfo{$Version}{"info_type"}{$1}=$2;
2264 $LibInfo{$Version}{"info"}{$1}=$3;
2265 }
2266
2267 # clean memory
2268 delete($Lines[$_]);
2269 }
2270
2271 # clean memory
2272 undef @Lines;
2273}
2274
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002275sub simplifyConstants()
2276{
2277 foreach my $Constant (keys(%{$Constants{$Version}}))
2278 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002279 if(defined $Constants{$Version}{$Constant}{"Header"})
2280 {
2281 my $Value = $Constants{$Version}{$Constant}{"Value"};
2282 if(defined $EnumConstants{$Version}{$Value}) {
2283 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2284 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002285 }
2286 }
2287}
2288
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002289sub simplifyNames()
2290{
2291 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2292 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002293 if($Typedef_Eq{$Version}{$Base}) {
2294 next;
2295 }
2296 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2297 if($#Translations==0)
2298 {
2299 if(length($Translations[0])<=length($Base)) {
2300 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2301 }
2302 }
2303 else
2304 { # select most appropriate
2305 foreach my $Tr (@Translations)
2306 {
2307 if($Base=~/\A\Q$Tr\E/)
2308 {
2309 $Typedef_Eq{$Version}{$Base} = $Tr;
2310 last;
2311 }
2312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002313 }
2314 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002315 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002316 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002317 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002318 if(not $TypeName) {
2319 next;
2320 }
2321 next if(index($TypeName,"<")==-1);# template instances only
2322 if($TypeName=~/>(::\w+)+\Z/)
2323 { # skip unused types
2324 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002325 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002326 foreach my $Base (sort {length($b)<=>length($a)}
2327 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002328 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002329 next if(not $Base);
2330 next if(index($TypeName,$Base)==-1);
2331 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002332 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002333 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002334 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2335 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2336 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002337 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002338 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2339 {
2340 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2341 {
2342 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2343 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002344 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002345 }
2346 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002347 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002348 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002349 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002350 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002351 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2352 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002353 }
2354}
2355
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002356sub setAnonTypedef_All()
2357{
2358 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2359 {
2360 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2361 {
2362 if(isAnon(getNameByInfo($InfoId))) {
2363 $TypedefToAnon{getTypeId($InfoId)} = 1;
2364 }
2365 }
2366 }
2367}
2368
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002369sub setTemplateParams_All()
2370{
2371 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2372 {
2373 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2374 setTemplateParams($_);
2375 }
2376 }
2377}
2378
2379sub setTemplateParams($)
2380{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002381 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002382 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002383 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002384 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002385 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002386 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002387 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002388 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002389 setTemplateInstParams($_[0], $TmplInst_Id);
2390 }
2391 }
2392
2393 $BasicTemplate{$Version}{$Tid} = $_[0];
2394
2395 if(my $Prms = getTreeAttr_Prms($_[0]))
2396 {
2397 if(my $Valu = getTreeAttr_Valu($Prms))
2398 {
2399 my $Vector = getTreeVec($Valu);
2400 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2401 {
2402 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2403 {
2404 if(my $Name = getNameByInfo($Val))
2405 {
2406 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2407 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2408 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2409 }
2410 else {
2411 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2412 }
2413 }
2414 }
2415 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002416 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002417 }
2418 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002419 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002420 {
2421 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2422 {
2423 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002424 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002425 }
2426 }
2427 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002428}
2429
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002430sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002431{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002432 my ($Tmpl, $Inst) = @_;
2433
2434 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002435 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002436 my ($Params_InfoId, $ElemId) = ();
2437 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2438 $Params_InfoId = $1;
2439 }
2440 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2441 $ElemId = $1;
2442 }
2443 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002444 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002445 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2446 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2447 {
2448 my ($PPos, $PTypeId) = ($1, $2);
2449 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2450 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002451 if($PType eq "template_type_parm") {
2452 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002453 }
2454 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002455 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2456 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002457 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002458 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002459 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002460 else
2461 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002462 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002463 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002464 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002465 }
2466 }
2467 }
2468}
2469
2470sub getTypeDeclId($)
2471{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002472 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002473 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002474 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2475 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2476 }
2477 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2478 {
2479 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2480 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2481 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002482 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002483 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002484 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002485}
2486
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002487sub getTypeInfo_All()
2488{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002489 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002490 { # support for GCC < 4.5
2491 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2492 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2493 # FIXME: check GCC versions
2494 addMissedTypes_Pre();
2495 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002496
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002497 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002498 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002499 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2500 if($IType=~/_type\Z/ and $IType ne "function_type"
2501 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002502 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002503 }
2504 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002505
2506 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002507 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002508 "Name" => "...",
2509 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002510 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002511 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002512 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002513
2514 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002515 { # support for GCC < 4.5
2516 addMissedTypes_Post();
2517 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002518
2519 if($ADD_TMPL_INSTANCES)
2520 {
2521 # templates
2522 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2523 {
2524 if(defined $TemplateMap{$Version}{$Tid}
2525 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2526 {
2527 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2528 {
2529 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2530 {
2531 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2532 {
2533 if(my %MAttr = getTypeAttr($MembTypeId))
2534 {
2535 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2536 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2537 }
2538 }
2539 }
2540 }
2541 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2542 {
2543 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2544 {
2545 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2546
2547 if($NBid ne $Bid)
2548 {
2549 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2550 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2551 }
2552 }
2553 }
2554 }
2555 }
2556 }
2557}
2558
2559sub createType($$)
2560{
2561 my ($Attr, $LibVersion) = @_;
2562 my $NewId = ++$MAX_ID;
2563
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002564 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002565 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002566 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002567
2568 return "$NewId";
2569}
2570
2571sub instType($$$)
2572{ # create template instances
2573 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002574
2575 if(not $TypeInfo{$LibVersion}{$Tid}) {
2576 return undef;
2577 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002578 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2579
2580 foreach my $Key (sort keys(%{$Map}))
2581 {
2582 if(my $Val = $Map->{$Key})
2583 {
2584 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2585
2586 if(defined $Attr->{"NameSpace"}) {
2587 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2588 }
2589 foreach (keys(%{$Attr->{"TParam"}})) {
2590 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2591 }
2592 }
2593 else
2594 { # remove absent
2595 # _Traits, etc.
2596 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002597 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002598 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2599 }
2600 foreach (keys(%{$Attr->{"TParam"}}))
2601 {
2602 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2603 delete($Attr->{"TParam"}{$_});
2604 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002605 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002606 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2607 }
2608 }
2609 }
2610 }
2611
2612 my $Tmpl = 0;
2613
2614 if(defined $Attr->{"TParam"})
2615 {
2616 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2617 {
2618 my $PName = $Attr->{"TParam"}{$_}{"name"};
2619
2620 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2621 {
2622 my %Base = get_BaseType($PTid, $LibVersion);
2623
2624 if($Base{"Type"} eq "TemplateParam"
2625 or defined $Base{"Template"})
2626 {
2627 $Tmpl = 1;
2628 last
2629 }
2630 }
2631 }
2632 }
2633
2634 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2635 return "$Id";
2636 }
2637 else
2638 {
2639 if(not $Tmpl) {
2640 delete($Attr->{"Template"});
2641 }
2642
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002643 my $New = createType($Attr, $LibVersion);
2644
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002645 my %EMap = ();
2646 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2647 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2648 }
2649 foreach (keys(%{$Map})) {
2650 $EMap{$_} = $Map->{$_};
2651 }
2652
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002653 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2654 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002655 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002656 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002657 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002658 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002659 {
2660 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2661
2662 if($NBid ne $Bid)
2663 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002664 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2665 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002666 }
2667 }
2668 }
2669
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002670 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002671 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002672 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2673 {
2674 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2675 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2676 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002677 }
2678 }
2679
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002680 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002681 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002682 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2683 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002684 }
2685 }
2686
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002687 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2688 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002689 }
2690
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002691 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002693}
2694
2695sub addMissedTypes_Pre()
2696{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002697 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002698 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2699 { # detecting missed typedefs
2700 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2701 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002702 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002703 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002704 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002705 if($TypeType eq "Unknown")
2706 { # template_type_parm
2707 next;
2708 }
2709 my $TypeDeclId = getTypeDeclId($TypeId);
2710 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2711 my $TypedefName = getNameByInfo($MissedTDid);
2712 next if(not $TypedefName);
2713 next if($TypedefName eq "__float80");
2714 next if(isAnon($TypedefName));
2715 if(not $TypeDeclId
2716 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002717 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002718 }
2719 }
2720 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002721 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002722 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002723 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002724 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002725 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002726 next;
2727 }
2728 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002729 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002730 if(not $TypedefName) {
2731 next;
2732 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002733 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002734 my %MissedInfo = ( # typedef info
2735 "Name" => $TypedefName,
2736 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002737 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002738 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002739 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002740 my ($H, $L) = getLocation($MissedTDid);
2741 $MissedInfo{"Header"} = $H;
2742 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002743 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002744 { # other types
2745 next;
2746 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002747 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002748 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002749 next;
2750 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002751 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002752 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002753 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002754 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002755 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002756 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002757 next;
2758 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002759 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002760 next;
2761 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002762 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002763 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002764 next;
2765 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002766 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002767 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002768 next;
2769 }
2770 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002771
2772 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2773
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002774 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002775 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002776 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002777 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002778 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002779
2780 # add missed & remove other
2781 $TypeInfo{$Version} = \%AddTypes;
2782 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002783}
2784
2785sub addMissedTypes_Post()
2786{
2787 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2788 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002789 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2790 {
2791 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2792 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2793 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2794 }
2795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002796 }
2797}
2798
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002799sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002800{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002801 my $TypeId = $_[0];
2802 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2803 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002804 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002805 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002806 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002807}
2808
2809sub getArraySize($$)
2810{
2811 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002812 if(my $Size = getSize($TypeId))
2813 {
2814 my $Elems = $Size/$BYTE_SIZE;
2815 while($BaseName=~s/\s*\[(\d+)\]//) {
2816 $Elems/=$1;
2817 }
2818 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2819 {
2820 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2821 $Elems/=$BasicSize;
2822 }
2823 }
2824 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002825 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002826 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002827}
2828
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002829sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002830{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002831 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002832 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002833 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2834 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002835 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002836 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2837 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2838 if(not $NodeType)
2839 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002840 return ();
2841 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002842 if($NodeType eq "tree_vec")
2843 {
2844 if($Pos!=$#Positions)
2845 { # select last vector of parameters ( ns<P1>::type<P2> )
2846 next;
2847 }
2848 }
2849 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2850 foreach my $P (@Params)
2851 {
2852 if($P eq "") {
2853 return ();
2854 }
2855 elsif($P ne "\@skip\@") {
2856 @TmplParams = (@TmplParams, $P);
2857 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002858 }
2859 }
2860 return @TmplParams;
2861}
2862
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002863sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002864{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002865 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002866 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002867 if(defined $TypeInfo{$Version}{$TypeId}
2868 and $TypeInfo{$Version}{$TypeId}{"Name"})
2869 { # already created
2870 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002871 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002872 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2873 { # incomplete type
2874 return ();
2875 }
2876 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2877
2878 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002879 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002880
2881 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2882 {
2883 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2884 {
2885 if($Info=~/qual[ ]*:/)
2886 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002887 my $NewId = ++$MAX_ID;
2888
2889 $MissedBase{$Version}{$TypeId} = "$NewId";
2890 $MissedBase_R{$Version}{$NewId} = $TypeId;
2891 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2892 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002893 }
2894 }
2895 $TypeAttr{"Type"} = "Typedef";
2896 }
2897 else {
2898 $TypeAttr{"Type"} = getTypeType($TypeId);
2899 }
2900
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002901 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2902 {
2903 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2904 { # local code
2905 return ();
2906 }
2907 }
2908
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002909 if($TypeAttr{"Type"} eq "Unknown") {
2910 return ();
2911 }
2912 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2913 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002914 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002915 if(my $TName = $TypeAttr{"Name"})
2916 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002917 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002918 $TName_Tid{$Version}{$TName} = $TypeId;
2919 return %TypeAttr;
2920 }
2921 else {
2922 return ();
2923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002924 }
2925 elsif($TypeAttr{"Type"} eq "Array")
2926 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002927 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2928 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002929 return ();
2930 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002931 if(my $Algn = getAlgn($TypeId)) {
2932 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2933 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002934 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002935 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002936 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002937 if(not $BTAttr{"Name"}) {
2938 return ();
2939 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002940 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002941 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002942 if(my $Size = getSize($TypeId)) {
2943 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2944 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002945 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002946 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2947 }
2948 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002949 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002950 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002951 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002952 else
2953 {
2954 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002955 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002956 $TypeAttr{"Name"} = $1."[]".$2;
2957 }
2958 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002959 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002961 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002962 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002963 if($BTAttr{"Header"}) {
2964 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002965 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002966 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002967 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2968 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002969 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002970 return ();
2971 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002972 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002973 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002974 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002975 if($TypeAttr{"Name"})
2976 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002977 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002978
2979 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2980 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002981 { # NOTE: register only one int: with built-in decl
2982 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2983 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2984 }
2985 }
2986 return %TypeAttr;
2987 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002988 else {
2989 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002990 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002991 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002992 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2993 {
2994 %TypeAttr = getTrivialTypeAttr($TypeId);
2995 if($TypeAttr{"Name"})
2996 {
2997 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2998 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2999 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3000 }
3001 return %TypeAttr;
3002 }
3003 else {
3004 return ();
3005 }
3006 }
3007 elsif($TypeAttr{"Type"} eq "SizeOf")
3008 {
3009 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
3010 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
3011 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
3012 if($TypeAttr{"Name"})
3013 {
3014 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
3015 return %TypeAttr;
3016 }
3017 else {
3018 return ();
3019 }
3020 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003021 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003022 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003023 my ($BTid, $BTSpec) = selectBaseType($TypeId);
3024 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003025 return ();
3026 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003027 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003028 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003029 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003030 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003031 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003032 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003033 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003035 }
3036 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003037 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003038 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003039 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003040 return ();
3041 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003042 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003043 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003044 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003045 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003046 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003047 }
3048 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003049 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003050 {
3051 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003052 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003053 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003054 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003055 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
3056 }
3057 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003058 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003059 }
3060 }
3061 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003062 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003063 }
3064 if($TypeAttr{"Type"} eq "Typedef")
3065 {
3066 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003067
3068 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
3069 return ();
3070 }
3071
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003072 if(isAnon($TypeAttr{"Name"}))
3073 { # anon typedef to anon type: ._N
3074 return ();
3075 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003076
3077 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
3078 { # artificial typedef of "struct X" to "X"
3079 $TypeAttr{"Artificial"} = 1;
3080 }
3081
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003082 if(my $NS = getNameSpace($TypeDeclId))
3083 {
3084 my $TypeName = $TypeAttr{"Name"};
3085 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
3086 { # "some_type" is the typedef to "struct some_type" in C++
3087 if($3) {
3088 $TypeAttr{"Name"} = $3."::".$TypeName;
3089 }
3090 }
3091 else
3092 {
3093 $TypeAttr{"NameSpace"} = $NS;
3094 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003095
3096 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
3097 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
3098 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003099 if($BTAttr{"NameSpace"}
3100 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003101 { # types like "std::fpos<__mbstate_t>" are
3102 # not covered by typedefs in the TU dump
3103 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003104 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3105 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003106 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003107 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003108 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003109 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003110 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003111 }
3112 }
3113 }
3114 }
3115 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003116 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003117 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003118 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003119 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3120 { # typedef int*const TYPEDEF; // first
3121 # int foo(TYPEDEF p); // const is optimized out
3122 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3123 if($BTAttr{"Name"}=~/</)
3124 {
3125 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3126 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3127 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003128 }
3129 }
3130 }
3131 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3132 }
3133 if(not $TypeAttr{"Size"})
3134 {
3135 if($TypeAttr{"Type"} eq "Pointer") {
3136 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3137 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003138 elsif($BTAttr{"Size"}) {
3139 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003140 }
3141 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003142 if(my $Algn = getAlgn($TypeId)) {
3143 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3144 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003145 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003146 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3147 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003148 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003149 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003150 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003151 { # typedef to "class Class"
3152 # should not be registered in TName_Tid
3153 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3154 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003156 }
3157 return %TypeAttr;
3158 }
3159}
3160
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003161sub getTreeVec($)
3162{
3163 my %Vector = ();
3164 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3165 {
3166 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3167 { # string length is N-1 because of the null terminator
3168 $Vector{$1} = $2;
3169 }
3170 }
3171 return \%Vector;
3172}
3173
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003174sub get_TemplateParam($$)
3175{
3176 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003177 return () if(not $Type_Id);
3178 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3179 return () if(not $NodeType);
3180 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003181 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003182 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003183 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003184 my $Num = getNodeIntCst($Type_Id);
3185 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003186 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003187 }
3188 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003189 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003190 }
3191 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003192 elsif($NodeType eq "string_cst") {
3193 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003194 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003195 elsif($NodeType eq "tree_vec")
3196 {
3197 my $Vector = getTreeVec($Type_Id);
3198 my @Params = ();
3199 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3200 {
3201 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3202 push(@Params, $P2);
3203 }
3204 }
3205 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003206 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003207 elsif($NodeType eq "parm_decl")
3208 {
3209 (getNameByInfo($Type_Id));
3210 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003211 else
3212 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003213 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003214 my $PName = $ParamAttr{"Name"};
3215 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003216 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003217 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003218 if($PName=~/\>/)
3219 {
3220 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003221 $PName = $Cover;
3222 }
3223 }
3224 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003225 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003226 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3227 # template<typename _Key, typename _Compare = std::less<_Key>
3228 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3229 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3230 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3231 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003232 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003233 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003234 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003235 }
3236}
3237
3238sub cover_stdcxx_typedef($)
3239{
3240 my $TypeName = $_[0];
3241 if(my @Covers = sort {length($a)<=>length($b)}
3242 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3243 { # take the shortest typedef
3244 # FIXME: there may be more than
3245 # one typedefs to the same type
3246 return $Covers[0];
3247 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003248 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003249 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3250 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3251 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003252 if(my $Cover = $Covers[0])
3253 {
3254 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3255 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3256 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003257 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003258 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003259}
3260
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003261sub getNodeIntCst($)
3262{
3263 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003264 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003265 if($EnumMembName_Id{$Version}{$CstId}) {
3266 return $EnumMembName_Id{$Version}{$CstId};
3267 }
3268 elsif((my $Value = getTreeValue($CstId)) ne "")
3269 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003270 if($Value eq "0")
3271 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003272 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003273 return "false";
3274 }
3275 else {
3276 return "0";
3277 }
3278 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003279 elsif($Value eq "1")
3280 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003281 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003282 return "true";
3283 }
3284 else {
3285 return "1";
3286 }
3287 }
3288 else {
3289 return $Value;
3290 }
3291 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003292 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003293}
3294
3295sub getNodeStrCst($)
3296{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003297 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3298 {
3299 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003300 {
3301 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3302 { # string length is N-1 because of the null terminator
3303 return substr($1, 0, $2-1);
3304 }
3305 else
3306 { # identifier_node
3307 return substr($1, 0, $2);
3308 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003309 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003310 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003311 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003312}
3313
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003314sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003315{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003316 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003317 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3318 if($Type eq "FieldPtr") {
3319 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3320 }
3321 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3322 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003323 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003324 if($Type eq "MethodPtr")
3325 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003326 if(my $Size = getSize($TypeId))
3327 {
3328 $Size/=$BYTE_SIZE;
3329 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003330 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003331 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003332 if(my $Algn = getAlgn($TypeId)) {
3333 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3334 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003335 # Return
3336 if($Type eq "FieldPtr")
3337 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003338 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003339 if($ReturnAttr{"Name"}) {
3340 $MemPtrName .= $ReturnAttr{"Name"};
3341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003342 $TypeAttr{"Return"} = $PtrId;
3343 }
3344 else
3345 {
3346 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3347 {
3348 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003349 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3350 if(not $ReturnAttr{"Name"})
3351 { # templates
3352 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003353 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003354 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003355 $TypeAttr{"Return"} = $ReturnTypeId;
3356 }
3357 }
3358 # Class
3359 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3360 {
3361 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003362 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003363 if($Class{"Name"}) {
3364 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3365 }
3366 else {
3367 $MemPtrName .= " (*)";
3368 }
3369 }
3370 else {
3371 $MemPtrName .= " (*)";
3372 }
3373 # Parameters
3374 if($Type eq "FuncPtr"
3375 or $Type eq "MethodPtr")
3376 {
3377 my @ParamTypeName = ();
3378 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3379 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003380 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003381 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003382 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003383 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003384 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3385 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003386 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003387 my $PTypeId = $1;
3388 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003389 if(not $ParamAttr{"Name"})
3390 { # templates (template_type_parm), etc.
3391 return ();
3392 }
3393 if($ParamAttr{"Name"} eq "void") {
3394 last;
3395 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003396 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003397 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003398 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003399 push(@ParamTypeName, $ParamAttr{"Name"});
3400 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003401 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3402 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003403 }
3404 else {
3405 last;
3406 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003407 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003408 else {
3409 last;
3410 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003411 }
3412 }
3413 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3414 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003415 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003416 return %TypeAttr;
3417}
3418
3419sub getTreeTypeName($)
3420{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003421 my $TypeId = $_[0];
3422 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003423 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003424 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003425 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003426 if(my $Name = getNameByInfo($TypeId))
3427 { # bit_size_type
3428 return $Name;
3429 }
3430 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003431 return "unsigned int";
3432 }
3433 else {
3434 return "int";
3435 }
3436 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003437 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003438 return getNameByInfo($1);
3439 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003440 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003441 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003442}
3443
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003444sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003445{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003446 my $Ptd = pointTo($_[0]);
3447 return 0 if(not $Ptd);
3448 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003449 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003450 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3451 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003452 }
3453 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003454 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3455 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003456 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003457 if($InfoT1 eq "pointer_type"
3458 and $InfoT2 eq "function_type") {
3459 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003460 }
3461 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003462 return 0;
3463}
3464
3465sub isMethodPtr($)
3466{
3467 my $Ptd = pointTo($_[0]);
3468 return 0 if(not $Ptd);
3469 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3470 {
3471 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3472 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3473 and $Info=~/ ptrmem /) {
3474 return 1;
3475 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003476 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003477 return 0;
3478}
3479
3480sub isFieldPtr($)
3481{
3482 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3483 {
3484 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3485 and $Info=~/ ptrmem /) {
3486 return 1;
3487 }
3488 }
3489 return 0;
3490}
3491
3492sub pointTo($)
3493{
3494 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3495 {
3496 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3497 return $1;
3498 }
3499 }
3500 return "";
3501}
3502
3503sub getTypeTypeByTypeId($)
3504{
3505 my $TypeId = $_[0];
3506 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3507 {
3508 my $NType = $NodeType{$TType};
3509 if($NType eq "Intrinsic") {
3510 return $NType;
3511 }
3512 elsif(isFuncPtr($TypeId)) {
3513 return "FuncPtr";
3514 }
3515 elsif(isMethodPtr($TypeId)) {
3516 return "MethodPtr";
3517 }
3518 elsif(isFieldPtr($TypeId)) {
3519 return "FieldPtr";
3520 }
3521 elsif($NType ne "Other") {
3522 return $NType;
3523 }
3524 }
3525 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003526}
3527
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003528my %UnQual = (
3529 "r"=>"restrict",
3530 "v"=>"volatile",
3531 "c"=>"const",
3532 "cv"=>"const volatile"
3533);
3534
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003535sub getQual($)
3536{
3537 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003538 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3539 {
3540 my ($Qual, $To) = ();
3541 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3542 $Qual = $UnQual{$1};
3543 }
3544 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3545 $To = $1;
3546 }
3547 if($Qual and $To) {
3548 return ($Qual, $To);
3549 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003550 }
3551 return ();
3552}
3553
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003554sub getQualType($)
3555{
3556 if($_[0] eq "const volatile") {
3557 return "ConstVolatile";
3558 }
3559 return ucfirst($_[0]);
3560}
3561
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003562sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003563{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003564 my $TypeId = $_[0];
3565 my $TypeDeclId = getTypeDeclId($TypeId);
3566 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003567 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003568 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3569 return "Typedef";
3570 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003571 }
3572 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3573 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003574 if(($Qual or $To) and $TypeDeclId
3575 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003576 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003577 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003578 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003579 elsif(not $MissedBase_R{$Version}{$TypeId}
3580 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003581 return "Typedef";
3582 }
3583 elsif($Qual)
3584 { # qualified types
3585 return getQualType($Qual);
3586 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003587
3588 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3589 { # typedef struct { ... } name
3590 $TypeTypedef{$Version}{$TypeId} = $1;
3591 }
3592
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003593 my $TypeType = getTypeTypeByTypeId($TypeId);
3594 if($TypeType eq "Struct")
3595 {
3596 if($TypeDeclId
3597 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3598 return "Template";
3599 }
3600 }
3601 return $TypeType;
3602}
3603
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003604sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003605{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003606 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003607 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003608 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3609 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3610 return 0;
3611 }
3612 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3613 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003614 if(my $TDid = getTypeDeclId($_[0]))
3615 {
3616 if(getTypeId($TDid) eq $_[0]
3617 and getNameByInfo($TDid))
3618 {
3619 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3620 return $1;
3621 }
3622 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003623 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003624 }
3625 }
3626 return 0;
3627}
3628
3629sub selectBaseType($)
3630{
3631 my $TypeId = $_[0];
3632 if(defined $MissedTypedef{$Version}{$TypeId})
3633 { # add missed typedefs
3634 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3635 return ($TypeId, "");
3636 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003637 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003638 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3639 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003640
3641 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3642 my $MB = $MissedBase{$Version}{$TypeId};
3643
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003644 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003645 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003646 and (getTypeId($1) ne $TypeId)
3647 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003648 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003649 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003650 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003651 elsif($MB)
3652 { # add base
3653 return ($MB, "");
3654 }
3655 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003656 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003657 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003658 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003659 elsif($Qual or $To)
3660 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003661 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003662 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003663 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003664 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003665 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003666 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003667 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003668 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003669 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003670 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003671 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003672 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003674 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003675 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003676 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003677 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003678 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003679 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003680 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003681
3682 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003683}
3684
3685sub getSymbolInfo_All()
3686{
3687 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3688 { # reverse order
3689 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003690 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003691 }
3692 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003693
3694 if($ADD_TMPL_INSTANCES)
3695 {
3696 # templates
3697 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3698 {
3699 my %Map = ();
3700
3701 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3702 {
3703 if(defined $TemplateMap{$Version}{$ClassId})
3704 {
3705 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3706 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3707 }
3708 }
3709 }
3710
3711 if(defined $TemplateMap{$Version}{$Sid})
3712 {
3713 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3714 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3715 }
3716 }
3717
3718 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3719 {
3720 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3721 {
3722 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3723 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3724 }
3725 }
3726 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3727 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3728 }
3729 }
3730 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003731}
3732
3733sub getVarInfo_All()
3734{
3735 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3736 { # reverse order
3737 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003738 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003739 }
3740 }
3741}
3742
3743sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003744 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003745}
3746
3747sub getVarInfo($)
3748{
3749 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003750 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003751 {
3752 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3753 if($NSInfoType and $NSInfoType eq "function_decl") {
3754 return;
3755 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003756 }
3757 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3758 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3759 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3760 delete($SymbolInfo{$Version}{$InfoId});
3761 return;
3762 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003763 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003764 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003765 delete($SymbolInfo{$Version}{$InfoId});
3766 return;
3767 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003768 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3769 delete($SymbolInfo{$Version}{$InfoId});
3770 return;
3771 }
3772 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003773 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3774 {
3775 if($OSgroup eq "windows")
3776 { # cut the offset
3777 $MnglName=~s/\@\d+\Z//g;
3778 }
3779 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3780 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003781 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003782 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003783 { # validate mangled name
3784 delete($SymbolInfo{$Version}{$InfoId});
3785 return;
3786 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003787 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003788 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003789 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003790 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003791 }
3792 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3793 { # non-public global data
3794 delete($SymbolInfo{$Version}{$InfoId});
3795 return;
3796 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003797 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003798 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003799 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003800 if(not defined $TypeInfo{$Version}{$Rid}
3801 or not $TypeInfo{$Version}{$Rid}{"Name"})
3802 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003803 delete($SymbolInfo{$Version}{$InfoId});
3804 return;
3805 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003806 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3807 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003808 if(defined $Val) {
3809 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3810 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003811 }
3812 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003813 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3814 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003815 if(not defined $TypeInfo{$Version}{$ClassId}
3816 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3817 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003818 delete($SymbolInfo{$Version}{$InfoId});
3819 return;
3820 }
3821 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003822 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3823 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003824 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003825 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003826 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003827 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003828 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003829 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003830 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003831 if(not $CheckHeadersOnly)
3832 {
3833 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3834 {
3835 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3836 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3837 {
3838 if(link_symbol($ShortName, $Version, "-Deps"))
3839 { # "const" global data is mangled as _ZL... in the TU dump
3840 # but not mangled when compiling a C shared library
3841 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3842 }
3843 }
3844 }
3845 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003846 if($COMMON_LANGUAGE{$Version} eq "C++")
3847 {
3848 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3849 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003850 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003851 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3852 }
3853 }
3854 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3855 { # try to mangle symbol (link with libraries)
3856 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3857 }
3858 if($OStarget eq "windows")
3859 {
3860 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3861 { # link MS C++ symbols from library with GCC symbols from headers
3862 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3863 }
3864 }
3865 }
3866 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3867 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3868 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003869 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3870 {
3871 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3872 { # non-target symbols
3873 delete($SymbolInfo{$Version}{$InfoId});
3874 return;
3875 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003876 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003877 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3878 {
3879 if(defined $MissedTypedef{$Version}{$Rid})
3880 {
3881 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3882 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3883 }
3884 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003885 }
3886 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003887 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003888 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3889 }
3890 if($ShortName=~/\A(_Z|\?)/) {
3891 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3892 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003893
3894 if($ExtraDump) {
3895 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3896 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003897}
3898
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003899sub isConstType($$)
3900{
3901 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003902 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003903 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003904 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003905 }
3906 return ($Base{"Type"} eq "Const");
3907}
3908
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003909sub getTrivialName($$)
3910{
3911 my ($TypeInfoId, $TypeId) = @_;
3912 my %TypeAttr = ();
3913 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3914 if(not $TypeAttr{"Name"}) {
3915 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3916 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003917 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003918 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003919 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003920 if(isAnon($TypeAttr{"Name"}))
3921 {
3922 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003923 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003924 { # searching for a first not anon scope
3925 if($NSId eq $NameSpaceId) {
3926 last;
3927 }
3928 else
3929 {
3930 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3931 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003932 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003933 last;
3934 }
3935 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003936 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003937 }
3938 }
3939 else
3940 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003941 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003942 {
3943 if($NameSpaceId ne $TypeId) {
3944 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3945 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003946 }
3947 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003948 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003949 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3950 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003951 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003952 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003953 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003954 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003955 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003956 if($TypeAttr{"NameSpace"}) {
3957 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3958 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003959 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003960 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3961 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003962 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003963 my @TParams = getTParams($TypeId, "Type");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003964 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003965 }
3966 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3967}
3968
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003969sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003970{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003971 my $TypeId = $_[0];
3972 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003973
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003974 my %TypeAttr = ();
3975
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003976 if($TemplateDecl{$Version}{$TypeId})
3977 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003978 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003979 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003980
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003981 setTypeAccess($TypeId, \%TypeAttr);
3982 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3983 if(isBuiltIn($TypeAttr{"Header"}))
3984 {
3985 delete($TypeAttr{"Header"});
3986 delete($TypeAttr{"Line"});
3987 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003988 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003989 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3990 if(not $TypeAttr{"Name"}) {
3991 return ();
3992 }
3993 if(not $TypeAttr{"NameSpace"}) {
3994 delete($TypeAttr{"NameSpace"});
3995 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003996
3997 my $Tmpl = undef;
3998
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003999 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004000 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004001 $Tmpl = $BasicTemplate{$Version}{$TypeId};
4002
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004003 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004004 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004005 foreach my $Pos (0 .. $#TParams)
4006 {
4007 my $Val = $TParams[$Pos];
4008 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
4009
4010 if(not defined $TypeAttr{"Template"})
4011 {
4012 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
4013
4014 if($Base{"Type"} eq "TemplateParam"
4015 or defined $Base{"Template"}) {
4016 $TypeAttr{"Template"} = 1;
4017 }
4018 }
4019
4020 if($Tmpl)
4021 {
4022 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
4023 {
4024 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
4025
4026 if($Val eq $Arg) {
4027 $TypeAttr{"Template"} = 1;
4028 }
4029 }
4030 }
4031 }
4032
4033 if($Tmpl)
4034 {
4035 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
4036 {
4037 if($Pos>$#TParams)
4038 {
4039 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
4040 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
4041 }
4042 }
4043 }
4044 }
4045
4046 if($ADD_TMPL_INSTANCES)
4047 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004048 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004049 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004050 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004051 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004052 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004053 {
4054 if(my $Flds = getTreeAttr_Flds($MainInst)) {
4055 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
4056 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004057 }
4058 if(not getTreeAttr_Binf($TypeId))
4059 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004060 if(my $Binf = getTreeAttr_Binf($MainInst)) {
4061 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
4062 }
4063 }
4064 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004065 }
4066 }
4067 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004068
4069 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
4070
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004071 if(my $Size = getSize($TypeId))
4072 {
4073 $Size = $Size/$BYTE_SIZE;
4074 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004075 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004076 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004077 {
4078 if($ExtraDump)
4079 {
4080 if(not defined $TypeAttr{"Memb"}
4081 and not $Tmpl)
4082 { # declaration only
4083 $TypeAttr{"Forward"} = 1;
4084 }
4085 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004086 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004087
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004088 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004089 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004090 {
4091 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004092 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004093 }
4094 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004095 or $TypeAttr{"Type"} eq "Class")
4096 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004097 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004098 if($Skip) {
4099 return ();
4100 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004101 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004102 if(my $Algn = getAlgn($TypeId)) {
4103 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4104 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004105 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004106
4107 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4108 {
4109 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004110 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004111 {
4112 if(not isAnon($TypeAttr{"Name"})) {
4113 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4114 }
4115 }
4116 }
4117
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004118 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004119 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4120 {
4121 my @Entries = split(/\n/, $VTable);
4122 foreach (1 .. $#Entries)
4123 {
4124 my $Entry = $Entries[$_];
4125 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004126 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004127 }
4128 }
4129 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004130
4131 if($TypeAttr{"Type"} eq "Enum")
4132 {
4133 if(not $TypeAttr{"NameSpace"})
4134 {
4135 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4136 {
4137 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004138 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004139 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004140 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004141 "Header"=>$TypeAttr{"Header"}
4142 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004143 if(isAnon($TypeAttr{"Name"}))
4144 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004145 if($ExtraDump
4146 or is_target_header($TypeAttr{"Header"}, $Version))
4147 {
4148 %{$Constants{$Version}{$MName}} = (
4149 "Value" => $MVal,
4150 "Header" => $TypeAttr{"Header"}
4151 );
4152 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004153 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004154 }
4155 }
4156 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004157 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004158 {
4159 if(defined $TypedefToAnon{$TypeId}) {
4160 $TypeAttr{"AnonTypedef"} = 1;
4161 }
4162 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004163
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004164 return %TypeAttr;
4165}
4166
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004167sub simplifyVTable($)
4168{
4169 my $Content = $_[0];
4170 if($Content=~s/ \[with (.+)]//)
4171 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4172 if(my @Elems = separate_Params($1, 0, 0))
4173 {
4174 foreach my $Elem (@Elems)
4175 {
4176 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4177 {
4178 my ($Arg, $Val) = ($1, $2);
4179
4180 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4181 $Content=~s/,\s*$Arg\b//g;
4182 }
4183 else {
4184 $Content=~s/\b$Arg\b/$Val/g;
4185 }
4186 }
4187 }
4188 }
4189 }
4190
4191 return $Content;
4192}
4193
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004194sub detect_lang($)
4195{
4196 my $TypeId = $_[0];
4197 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004198 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004199 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004200 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4201 }
4202 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004203 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004204 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004205 while($Fncs)
4206 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004207 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004208 return 1;
4209 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004210 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004211 }
4212 }
4213 return 0;
4214}
4215
4216sub setSpec($$)
4217{
4218 my ($TypeId, $TypeAttr) = @_;
4219 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4220 if($Info=~/\s+spec\s+/) {
4221 $TypeAttr->{"Spec"} = 1;
4222 }
4223}
4224
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004225sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004226{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004227 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004228 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004229 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004230 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004231 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004232 my $Pos = 0;
4233 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4234 {
4235 my ($Access, $BInfoId) = ($1, $2);
4236 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004237 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4238 if(not $CType or $CType eq "template_type_parm"
4239 or $CType eq "typename_type")
4240 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004241 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004243 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004244 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004245 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4246 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004247 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004248 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4249 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004250 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004251 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004252 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004253 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4254 }
4255 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004256 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004257 }
4258 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004259 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004260}
4261
4262sub getBinfClassId($)
4263{
4264 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4265 $Info=~/type[ ]*:[ ]*@(\d+) /;
4266 return $1;
4267}
4268
4269sub unmangledFormat($$)
4270{
4271 my ($Name, $LibVersion) = @_;
4272 $Name = uncover_typedefs($Name, $LibVersion);
4273 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4274 $Name=~s/\(\w+\)(\d)/$1/;
4275 return $Name;
4276}
4277
4278sub modelUnmangled($$)
4279{
4280 my ($InfoId, $Compiler) = @_;
4281 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4282 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4283 }
4284 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4285 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4286 $PureSignature = "~".$PureSignature;
4287 }
4288 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4289 {
4290 my (@Params, @ParamTypes) = ();
4291 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4292 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4293 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4294 }
4295 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4296 { # checking parameters
4297 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004298 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004299 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004300 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004301
4302 if($PName eq "this"
4303 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4304 {
4305 next;
4306 }
4307
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004308 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004309 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004310 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004311 }
4312 @ParamTypes = (@ParamTypes, $PTName);
4313 }
4314 if(@ParamTypes) {
4315 $PureSignature .= "(".join(", ", @ParamTypes).")";
4316 }
4317 else
4318 {
4319 if($Compiler eq "MSVC")
4320 {
4321 $PureSignature .= "(void)";
4322 }
4323 else
4324 { # GCC
4325 $PureSignature .= "()";
4326 }
4327 }
4328 $PureSignature = delete_keywords($PureSignature);
4329 }
4330 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4331 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004332 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004333 $PureSignature = $ClassName."::".$PureSignature;
4334 }
4335 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4336 $PureSignature = $NS."::".$PureSignature;
4337 }
4338 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4339 $PureSignature .= " const";
4340 }
4341 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4342 $PureSignature .= " volatile";
4343 }
4344 my $ShowReturn = 0;
4345 if($Compiler eq "MSVC"
4346 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4347 {
4348 $ShowReturn=1;
4349 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004350 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4351 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004352 {
4353 $ShowReturn=1;
4354 }
4355 if($ShowReturn)
4356 { # mangled names for template function specializations include return value
4357 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4358 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004359 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004360 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4361 $PureSignature = $ReturnName." ".$PureSignature;
4362 }
4363 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004364 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004365}
4366
4367sub mangle_symbol($$$)
4368{ # mangling for simple methods
4369 # see gcc-4.6.0/gcc/cp/mangle.c
4370 my ($InfoId, $LibVersion, $Compiler) = @_;
4371 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4372 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4373 }
4374 my $Mangled = "";
4375 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004376 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004377 }
4378 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004379 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004380 }
4381 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4382}
4383
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004384sub mangle_symbol_MSVC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004385{
4386 my ($InfoId, $LibVersion) = @_;
4387 return "";
4388}
4389
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004390sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004391{ # see gcc-4.6.0/gcc/cp/mangle.c
4392 my ($InfoId, $LibVersion) = @_;
4393 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004394 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004395 my %Repl = ();# SN_ replacements
4396 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4397 {
4398 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4399 if($MangledClass!~/\AN/) {
4400 $MangledClass = "N".$MangledClass;
4401 }
4402 else {
4403 $MangledClass=~s/E\Z//;
4404 }
4405 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4406 $MangledClass=~s/\AN/NV/;
4407 }
4408 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4409 $MangledClass=~s/\AN/NK/;
4410 }
4411 $Mangled .= $MangledClass;
4412 }
4413 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4414 { # mangled by name due to the absence of structured info
4415 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4416 if($MangledNS!~/\AN/) {
4417 $MangledNS = "N".$MangledNS;
4418 }
4419 else {
4420 $MangledNS=~s/E\Z//;
4421 }
4422 $Mangled .= $MangledNS;
4423 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004424 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004425 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004426 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004427 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004428 foreach (@TPos) {
4429 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4430 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004431 }
4432 elsif($TmplParams)
4433 { # remangling mode
4434 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004435 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004436 }
4437 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4438 $Mangled .= "C1";
4439 }
4440 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4441 $Mangled .= "D0";
4442 }
4443 elsif($ShortName)
4444 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004445 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4446 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004447 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004448 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004449 { # "const" global data is mangled as _ZL...
4450 $Mangled .= "L";
4451 }
4452 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004453 if($ShortName=~/\Aoperator(\W.*)\Z/)
4454 {
4455 my $Op = $1;
4456 $Op=~s/\A[ ]+//g;
4457 if(my $OpMngl = $OperatorMangling{$Op}) {
4458 $Mangled .= $OpMngl;
4459 }
4460 else { # conversion operator
4461 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4462 }
4463 }
4464 else {
4465 $Mangled .= length($ShortName).$ShortName;
4466 }
4467 if(@TParams)
4468 { # templates
4469 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004470 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004471 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4472 }
4473 $Mangled .= "E";
4474 }
4475 if(not $ClassId and @TParams) {
4476 add_substitution($ShortName, \%Repl, 0);
4477 }
4478 }
4479 if($ClassId or $NameSpace) {
4480 $Mangled .= "E";
4481 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004482 if(@TParams)
4483 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004484 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004485 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4486 }
4487 }
4488 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4489 {
4490 my @Params = ();
4491 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4492 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4493 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4494 }
4495 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4496 { # checking parameters
4497 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4498 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4499 }
4500 if(not @Params) {
4501 $Mangled .= "v";
4502 }
4503 }
4504 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4505 $Mangled = write_stdcxx_substitution($Mangled);
4506 if($Mangled eq "_Z") {
4507 return "";
4508 }
4509 return $Mangled;
4510}
4511
4512sub correct_incharge($$$)
4513{
4514 my ($InfoId, $LibVersion, $Mangled) = @_;
4515 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4516 {
4517 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004518 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004519 }
4520 }
4521 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4522 {
4523 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004524 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004525 }
4526 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004527 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004528 }
4529 }
4530 return $Mangled;
4531}
4532
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004533sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004534{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004535 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004536 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004537 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004538 return $Name;
4539 }
4540 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004541 while(my $CPos = find_center($TParams, "<"))
4542 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004543 $TParams = substr($TParams, $CPos);
4544 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004545 if($TParams=~s/\A<(.+)>\Z/$1/) {
4546 $Name=~s/<\Q$TParams\E>\Z//;
4547 }
4548 else
4549 { # error
4550 $TParams = "";
4551 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004552 return ($Name, $TParams);
4553}
4554
4555sub get_sub_ns($)
4556{
4557 my $Name = $_[0];
4558 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004559 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004560 {
4561 push(@NS, substr($Name, 0, $CPos));
4562 $Name = substr($Name, $CPos);
4563 $Name=~s/\A:://;
4564 }
4565 return (join("::", @NS), $Name);
4566}
4567
4568sub mangle_ns($$$)
4569{
4570 my ($Name, $LibVersion, $Repl) = @_;
4571 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4572 {
4573 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4574 $Mangled=~s/\AN(.+)E\Z/$1/;
4575 return $Mangled;
4576
4577 }
4578 else
4579 {
4580 my ($MangledNS, $SubNS) = ("", "");
4581 ($SubNS, $Name) = get_sub_ns($Name);
4582 if($SubNS) {
4583 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4584 }
4585 $MangledNS .= length($Name).$Name;
4586 add_substitution($MangledNS, $Repl, 0);
4587 return $MangledNS;
4588 }
4589}
4590
4591sub mangle_param($$$)
4592{
4593 my ($PTid, $LibVersion, $Repl) = @_;
4594 my ($MPrefix, $Mangled) = ("", "");
4595 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004596 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004597 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004598 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004599 if(not $BaseType_Name) {
4600 return "";
4601 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004602 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004603 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004604 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4605 while($Suffix=~/(&|\*|const)\Z/)
4606 {
4607 if($Suffix=~s/[ ]*&\Z//) {
4608 $MPrefix .= "R";
4609 }
4610 if($Suffix=~s/[ ]*\*\Z//) {
4611 $MPrefix .= "P";
4612 }
4613 if($Suffix=~s/[ ]*const\Z//)
4614 {
4615 if($MPrefix=~/R|P/
4616 or $Suffix=~/&|\*/) {
4617 $MPrefix .= "K";
4618 }
4619 }
4620 if($Suffix=~s/[ ]*volatile\Z//) {
4621 $MPrefix .= "V";
4622 }
4623 #if($Suffix=~s/[ ]*restrict\Z//) {
4624 #$MPrefix .= "r";
4625 #}
4626 }
4627 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4628 $Mangled .= $Token;
4629 }
4630 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4631 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004632 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004633 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004634 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004635 foreach (@TPos) {
4636 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4637 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004638 }
4639 elsif($TmplParams)
4640 { # remangling mode
4641 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004642 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004643 }
4644 my $MangledNS = "";
4645 my ($SubNS, $SName) = get_sub_ns($ShortName);
4646 if($SubNS) {
4647 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4648 }
4649 $MangledNS .= length($SName).$SName;
4650 if(@TParams) {
4651 add_substitution($MangledNS, $Repl, 0);
4652 }
4653 $Mangled .= "N".$MangledNS;
4654 if(@TParams)
4655 { # templates
4656 $Mangled .= "I";
4657 foreach my $TParam (@TParams) {
4658 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4659 }
4660 $Mangled .= "E";
4661 }
4662 $Mangled .= "E";
4663 }
4664 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4665 {
4666 if($BaseType{"Type"} eq "MethodPtr") {
4667 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4668 }
4669 else {
4670 $Mangled .= "PF";
4671 }
4672 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4673 my @Params = keys(%{$BaseType{"Param"}});
4674 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4675 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4676 }
4677 if(not @Params) {
4678 $Mangled .= "v";
4679 }
4680 $Mangled .= "E";
4681 }
4682 elsif($BaseType{"Type"} eq "FieldPtr")
4683 {
4684 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4685 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4686 }
4687 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4688 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4689 {
4690 if($Mangled eq $Optimized)
4691 {
4692 if($ShortName!~/::/)
4693 { # remove "N ... E"
4694 if($MPrefix) {
4695 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4696 }
4697 else {
4698 $Mangled=~s/\AN(.+)E\Z/$1/g;
4699 }
4700 }
4701 }
4702 else {
4703 $Mangled = $Optimized;
4704 }
4705 }
4706 add_substitution($Mangled, $Repl, 1);
4707 return $Mangled;
4708}
4709
4710sub mangle_template_param($$$)
4711{ # types + literals
4712 my ($TParam, $LibVersion, $Repl) = @_;
4713 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4714 return mangle_param($TPTid, $LibVersion, $Repl);
4715 }
4716 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4717 { # class_name<1u>::method(...)
4718 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4719 }
4720 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4721 { # class_name<(signed char)1>::method(...)
4722 return "L".$IntrinsicMangling{$1}.$2."E";
4723 }
4724 elsif($TParam eq "true")
4725 { # class_name<true>::method(...)
4726 return "Lb1E";
4727 }
4728 elsif($TParam eq "false")
4729 { # class_name<true>::method(...)
4730 return "Lb0E";
4731 }
4732 else { # internal error
4733 return length($TParam).$TParam;
4734 }
4735}
4736
4737sub add_substitution($$$)
4738{
4739 my ($Value, $Repl, $Rec) = @_;
4740 if($Rec)
4741 { # subtypes
4742 my @Subs = ($Value);
4743 while($Value=~s/\A(R|P|K)//) {
4744 push(@Subs, $Value);
4745 }
4746 foreach (reverse(@Subs)) {
4747 add_substitution($_, $Repl, 0);
4748 }
4749 return;
4750 }
4751 return if($Value=~/\AS(\d*)_\Z/);
4752 $Value=~s/\AN(.+)E\Z/$1/g;
4753 return if(defined $Repl->{$Value});
4754 return if(length($Value)<=1);
4755 return if($StdcxxMangling{$Value});
4756 # check for duplicates
4757 my $Base = $Value;
4758 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4759 {
4760 my $Num = $Repl->{$Type};
4761 my $Replace = macro_mangle($Num);
4762 $Base=~s/\Q$Replace\E/$Type/;
4763 }
4764 if(my $OldNum = $Repl->{$Base})
4765 {
4766 $Repl->{$Value} = $OldNum;
4767 return;
4768 }
4769 my @Repls = sort {$b<=>$a} values(%{$Repl});
4770 if(@Repls) {
4771 $Repl->{$Value} = $Repls[0]+1;
4772 }
4773 else {
4774 $Repl->{$Value} = -1;
4775 }
4776 # register duplicates
4777 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004778 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004779 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4780 {
4781 next if($Base eq $Type);
4782 my $Num = $Repl->{$Type};
4783 my $Replace = macro_mangle($Num);
4784 $Base=~s/\Q$Type\E/$Replace/;
4785 $Repl->{$Base} = $Repl->{$Value};
4786 }
4787}
4788
4789sub macro_mangle($)
4790{
4791 my $Num = $_[0];
4792 if($Num==-1) {
4793 return "S_";
4794 }
4795 else
4796 {
4797 my $Code = "";
4798 if($Num<10)
4799 { # S0_, S1_, S2_, ...
4800 $Code = $Num;
4801 }
4802 elsif($Num>=10 and $Num<=35)
4803 { # SA_, SB_, SC_, ...
4804 $Code = chr(55+$Num);
4805 }
4806 else
4807 { # S10_, S11_, S12_
4808 $Code = $Num-26; # 26 is length of english alphabet
4809 }
4810 return "S".$Code."_";
4811 }
4812}
4813
4814sub write_stdcxx_substitution($)
4815{
4816 my $Mangled = $_[0];
4817 if($StdcxxMangling{$Mangled}) {
4818 return $StdcxxMangling{$Mangled};
4819 }
4820 else
4821 {
4822 my @Repls = keys(%StdcxxMangling);
4823 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4824 foreach my $MangledType (@Repls)
4825 {
4826 my $Replace = $StdcxxMangling{$MangledType};
4827 #if($Mangled!~/$Replace/) {
4828 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4829 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4830 #}
4831 }
4832 }
4833 return $Mangled;
4834}
4835
4836sub write_substitution($$)
4837{
4838 my ($Mangled, $Repl) = @_;
4839 if(defined $Repl->{$Mangled}
4840 and my $MnglNum = $Repl->{$Mangled}) {
4841 $Mangled = macro_mangle($MnglNum);
4842 }
4843 else
4844 {
4845 my @Repls = keys(%{$Repl});
4846 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4847 # FIXME: how to apply replacements? by num or by pos
4848 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4849 foreach my $MangledType (@Repls)
4850 {
4851 my $Replace = macro_mangle($Repl->{$MangledType});
4852 if($Mangled!~/$Replace/) {
4853 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4854 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4855 }
4856 }
4857 }
4858 return $Mangled;
4859}
4860
4861sub delete_keywords($)
4862{
4863 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004864 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004865 return $TypeName;
4866}
4867
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004868sub uncover_typedefs($$)
4869{
4870 my ($TypeName, $LibVersion) = @_;
4871 return "" if(not $TypeName);
4872 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4873 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4874 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004875 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004876 while($TypeName_New ne $TypeName_Pre)
4877 {
4878 $TypeName_Pre = $TypeName_New;
4879 my $TypeName_Copy = $TypeName_New;
4880 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004881 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004882 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004883 if(not $Intrinsic_Keywords{$1}) {
4884 $Words{$1} = 1;
4885 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004886 }
4887 foreach my $Word (keys(%Words))
4888 {
4889 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4890 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004891 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004892 if($BaseType_Name=~/\([\*]+\)/)
4893 { # FuncPtr
4894 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4895 {
4896 my $Type_Suffix = $1;
4897 $TypeName_New = $BaseType_Name;
4898 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004899 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004900 }
4901 }
4902 }
4903 else
4904 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004905 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004906 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004907 }
4908 }
4909 }
4910 }
4911 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4912}
4913
4914sub isInternal($)
4915{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004916 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4917 {
4918 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4919 {
4920 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4921 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4922 return 1;
4923 }
4924 }
4925 }
4926 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004927}
4928
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004929sub getDataVal($$)
4930{
4931 my ($InfoId, $TypeId) = @_;
4932 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4933 {
4934 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4935 {
4936 if(defined $LibInfo{$Version}{"info_type"}{$1}
4937 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004938 {
4939 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004940 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004941 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4942 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004943 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004944 if(my $Addr = getTreeAttr_Op($1)) {
4945 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004946 }
4947 }
4948 }
4949 }
4950 else {
4951 return getInitVal($1, $TypeId);
4952 }
4953 }
4954 }
4955 return undef;
4956}
4957
4958sub getInitVal($$)
4959{
4960 my ($InfoId, $TypeId) = @_;
4961 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4962 {
4963 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4964 {
4965 if($InfoType eq "integer_cst")
4966 {
4967 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004968 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004969 { # characters
4970 $Val = chr($Val);
4971 }
4972 return $Val;
4973 }
4974 elsif($InfoType eq "string_cst") {
4975 return getNodeStrCst($InfoId);
4976 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004977 elsif($InfoType eq "var_decl")
4978 {
4979 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4980 return $Name;
4981 }
4982 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004983 }
4984 }
4985 return undef;
4986}
4987
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004988sub set_Class_And_Namespace($)
4989{
4990 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004991 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004992 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004993 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004994 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004995 my $NSInfoId = $1;
4996 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4997 {
4998 if($InfoType eq "namespace_decl") {
4999 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
5000 }
5001 elsif($InfoType eq "record_type") {
5002 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
5003 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005004 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005005 }
5006 }
5007 if($SymbolInfo{$Version}{$InfoId}{"Class"}
5008 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005009 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005010 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005011 { # skip
5012 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005014 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005015
5016 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005017}
5018
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005019sub debugMangling($)
5020{
5021 my $LibVersion = $_[0];
5022 my %Mangled = ();
5023 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
5024 {
5025 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
5026 {
5027 if($Mngl=~/\A(_Z|\?)/) {
5028 $Mangled{$Mngl}=$InfoId;
5029 }
5030 }
5031 }
5032 translateSymbols(keys(%Mangled), $LibVersion);
5033 foreach my $Mngl (keys(%Mangled))
5034 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005035 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
5036 my $U2 = $tr_name{$Mngl};
5037 if($U1 ne $U2) {
5038 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005039 }
5040 }
5041}
5042
5043sub linkSymbol($)
5044{ # link symbols from shared libraries
5045 # with the symbols from header files
5046 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005047 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005048 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005049 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5050 or $EMERGENCY_MODE_48)
5051 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
5052 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
5053 # GCC 4.8 doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005054 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005055 {
5056 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
5057 return correct_incharge($InfoId, $Version, $Mangled);
5058 }
5059 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005060 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005061 or not $BinaryOnly
5062 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005063 { # 1. --headers-only mode
5064 # 2. not mangled src-only symbols
5065 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
5066 return $Mangled;
5067 }
5068 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005069 }
5070 return "";
5071}
5072
5073sub setLanguage($$)
5074{
5075 my ($LibVersion, $Lang) = @_;
5076 if(not $UserLang) {
5077 $COMMON_LANGUAGE{$LibVersion} = $Lang;
5078 }
5079}
5080
5081sub getSymbolInfo($)
5082{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005083 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005084 if(isInternal($InfoId)) {
5085 return;
5086 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005087 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5088 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005089 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5090 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005091 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005092 return;
5093 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005094 setFuncAccess($InfoId);
5095 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005096 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5097 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005098 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005099 return;
5100 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005101
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005102 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005103 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005104 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005105 if(not defined $TypeInfo{$Version}{$Return}
5106 or not $TypeInfo{$Version}{$Return}{"Name"})
5107 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005108 delete($SymbolInfo{$Version}{$InfoId});
5109 return;
5110 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005111 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005112 }
5113 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5114 {
5115 if(defined $MissedTypedef{$Version}{$Rid})
5116 {
5117 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5118 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5119 }
5120 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005121 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005122 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5123 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005124 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005125 my $Orig = getFuncOrig($InfoId);
5126 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005127 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5128 {
5129 delete($SymbolInfo{$Version}{$InfoId});
5130 return;
5131 }
5132
5133 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005134 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005135 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005136 return;
5137 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005138
5139 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005140 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005141 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5142
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005143 my @TParams = getTParams($Orig, "Func");
5144 if(not @TParams)
5145 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005146 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005147 return;
5148 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005149 foreach my $Pos (0 .. $#TParams)
5150 {
5151 my $Val = $TParams[$Pos];
5152 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5153
5154 if($Tmpl)
5155 {
5156 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5157 {
5158 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5159 }
5160 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005161 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005162
5163 if($Tmpl)
5164 {
5165 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5166 {
5167 if($Pos>$#TParams)
5168 {
5169 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5170 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5171 }
5172 }
5173 }
5174
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005175 my $PrmsInLine = join(", ", @TParams);
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005176 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5177 { # operator<< <T>, operator>> <T>
5178 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5179 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005180 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".$PrmsInLine.">";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005181 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005182 }
5183 else
5184 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005185 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005186 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005187 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5188 {
5189 if($OSgroup eq "windows")
5190 { # cut the offset
5191 $MnglName=~s/\@\d+\Z//g;
5192 }
5193 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5194
5195 # NOTE: mangling of some symbols may change depending on GCC version
5196 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5197 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5198 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005199
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005200 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005201 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005202 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005203 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005204 return;
5205 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005206 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005207 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005208 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005209 if($Skip)
5210 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005211 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005212 return;
5213 }
5214 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005215 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5216 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5217 }
5218
5219 if(set_Class_And_Namespace($InfoId))
5220 {
5221 delete($SymbolInfo{$Version}{$InfoId});
5222 return;
5223 }
5224
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005225 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5226 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005227 if(not defined $TypeInfo{$Version}{$ClassId}
5228 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5229 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005230 delete($SymbolInfo{$Version}{$InfoId});
5231 return;
5232 }
5233 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005234 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5235 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005236 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005237 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005238 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005239 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005240 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005241 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005242 }
5243 if($COMMON_LANGUAGE{$Version} eq "C++")
5244 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005245 # C++ or --headers-only mode
5246 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005247 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005248 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5249 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005250 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005251 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005252 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005253 if(my $Mangled = linkSymbol($InfoId)) {
5254 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005255 }
5256 }
5257 if($OStarget eq "windows")
5258 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005259 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005260 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005261 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005262 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005263 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005264 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005265 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005266 }
5267 }
5268 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005269 else
5270 { # not mangled in C
5271 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5272 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005273 if(not $CheckHeadersOnly
5274 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5275 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5276 {
5277 my $Incorrect = 0;
5278
5279 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5280 {
5281 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5282 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5283 { # mangled in the TU dump, but not mangled in the library
5284 $Incorrect = 1;
5285 }
5286 }
5287 else
5288 {
5289 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5290 { # all C++ functions are not mangled in the TU dump
5291 $Incorrect = 1;
5292 }
5293 }
5294 if($Incorrect)
5295 {
5296 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5297 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5298 }
5299 }
5300 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005301 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005302 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005303 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005304 return;
5305 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005306 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005307 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005308 { # identify virtual and pure virtual functions
5309 # NOTE: constructors cannot be virtual
5310 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5311 # in the TU dump, so taking it from the original symbol
5312 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5313 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5314 { # NOTE: D2 destructors are not present in a v-table
5315 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005317 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005318 if(isInline($InfoId)) {
5319 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005320 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005321 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005322 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5323 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005324 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5325 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005326 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005327 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005328 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005329 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005330 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005331 }
5332 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005333 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5334 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005335 if(not $ExtraDump)
5336 {
5337 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5338 { # non-target symbols
5339 delete($SymbolInfo{$Version}{$InfoId});
5340 return;
5341 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005342 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005343 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005344 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5345 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5346 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5347 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005348 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005349 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5350 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005351 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005352 return;
5353 }
5354 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005355 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005356 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005357 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005358 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005359 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005360 return;
5361 }
5362 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005363 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005364 }
5365 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005366 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5367 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5368 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005369 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005370 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5371 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005372 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005373 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005374 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005375 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005376 }
5377 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005378 if(getFuncLink($InfoId) eq "Static") {
5379 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005380 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005381 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5382 {
5383 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5384 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005385 if($Unmangled=~/\.\_\d/)
5386 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005387 delete($SymbolInfo{$Version}{$InfoId});
5388 return;
5389 }
5390 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005391 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005392
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005393 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5394 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005395 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005396 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5397 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005398 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005399
5400 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5401 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5402 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005403
5404 if($ExtraDump) {
5405 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5406 }
5407}
5408
5409sub guessHeader($)
5410{
5411 my $InfoId = $_[0];
5412 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5413 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5414 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5415 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5416 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5417 {
5418 if(get_filename($HPath) eq $Header)
5419 {
5420 my $HDir = get_filename(get_dirname($HPath));
5421 if($HDir ne "include"
5422 and $HDir=~/\A[a-z]+\Z/i) {
5423 return join_P($HDir, $Header);
5424 }
5425 }
5426 }
5427 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005428}
5429
5430sub isInline($)
5431{ # "body: undefined" in the tree
5432 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005433 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5434 {
5435 if($Info=~/ undefined /i) {
5436 return 0;
5437 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005438 }
5439 return 1;
5440}
5441
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005442sub hasThrow($)
5443{
5444 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5445 {
5446 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5447 return getTreeAttr_Unql($1, "unql");
5448 }
5449 }
5450 return 1;
5451}
5452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005453sub getTypeId($)
5454{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005455 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5456 {
5457 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5458 return $1;
5459 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005460 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005461 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005462}
5463
5464sub setTypeMemb($$)
5465{
5466 my ($TypeId, $TypeAttr) = @_;
5467 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005468 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005469 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005470 if($TypeType eq "Enum")
5471 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005472 my $MInfoId = getTreeAttr_Csts($TypeId);
5473 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005474 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005475 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5476 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005477 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005478 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5479 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005480 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005481 }
5482 }
5483 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5484 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005485 my $MInfoId = getTreeAttr_Flds($TypeId);
5486 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005487 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005488 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5489 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005490 if(not $IType or $IType ne "field_decl")
5491 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005492
5493 if($IType eq "var_decl")
5494 { # static field
5495 $StaticFields = 1;
5496 }
5497
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005498 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005499 next;
5500 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005501 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005502 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005503 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005504 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005505 }
5506 if(not $StructMembName)
5507 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005508 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005509 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005510 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005511 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5512 if(isAnon($UnnamedTName))
5513 { # rename unnamed fields to unnamed0, unnamed1, ...
5514 $StructMembName = "unnamed".($UnnamedPos++);
5515 }
5516 }
5517 }
5518 if(not $StructMembName)
5519 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005520 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005521 next;
5522 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005523 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005524 if(defined $MissedTypedef{$Version}{$MembTypeId})
5525 {
5526 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5527 $MembTypeId = $AddedTid;
5528 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005529 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005530
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005531 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5532 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005533 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005534 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005535 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5536 }
5537 if($MInfo=~/spec:\s*mutable /)
5538 { # mutable fields
5539 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005540 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005541 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005542 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5543 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005544 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005545 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005546 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005547 }
5548 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005549 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005550 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5551 { # template
5552 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5553 }
5554 else {
5555 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5556 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005557 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005558
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005559 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005560 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005561 }
5562 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005563
5564 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005565}
5566
5567sub setFuncParams($)
5568{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005569 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005570 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005571
5572 my $FType = getFuncType($InfoId);
5573
5574 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005575 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005576 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5577 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005578 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005579 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005580 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5581 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005582 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005583 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5584 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005585 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005586 else
5587 { # skip
5588 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005589 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005590 # skip "this"-parameter
5591 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005592 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005593 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005594 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005595 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005596 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5597 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5598 if(not $ParamName)
5599 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005600 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005601 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005602 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5603 {
5604 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5605 $ParamTypeId = $AddedTid;
5606 }
5607 }
5608 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005609 if(not $PType or $PType eq "Unknown") {
5610 return 1;
5611 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005612 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005613 if(not $PTName) {
5614 return 1;
5615 }
5616 if($PTName eq "void") {
5617 last;
5618 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005619 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005620 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005621 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005622 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005623 $ParamInfoId = getNextElem($ParamInfoId);
5624 next;
5625 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005626 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005627
5628 if(my %Base = get_BaseType($ParamTypeId, $Version))
5629 {
5630 if(defined $Base{"Template"}) {
5631 return 1;
5632 }
5633 }
5634
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005635 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005636 if(my $Algn = getAlgn($ParamInfoId)) {
5637 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5638 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005639 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5640 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005641 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005642 }
5643 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005644 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005645 if($ParamName ne "this" or $FType ne "Method") {
5646 $PPos += 1;
5647 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005648 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005649 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005650 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005651 }
5652 return 0;
5653}
5654
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005655sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005656{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005657 my ($InfoId, $Vtt_Pos) = @_;
5658 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005659 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005660 my $FType = getFuncType($InfoId);
5661
5662 if($FType eq "Method")
5663 {
5664 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005665 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005666 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005667 if(not $ParamListElemId)
5668 { # foo(...)
5669 return 1;
5670 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005671 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005672 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005673 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005674 { # actual params: may differ from formal args
5675 # formal int*const
5676 # actual: int*
5677 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005678 {
5679 $Vtt_Pos=-1;
5680 $ParamListElemId = getNextElem($ParamListElemId);
5681 next;
5682 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005683 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5684 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005685 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005686 $HaveVoid = 1;
5687 last;
5688 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005689 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005690 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005691 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5692 {
5693 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5694 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5695 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005696 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005697 }
5698 }
5699 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5700 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005701 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005702 { # params
5703 if($OldId ne $ParamTypeId)
5704 {
5705 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5706 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5707
5708 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5709 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5710 }
5711 }
5712 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005713 }
5714 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005715 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005716 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005717 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5718 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005719 if($PurpType eq "nop_expr")
5720 { # func ( const char* arg = (const char*)(void*)0 )
5721 $PurpId = getTreeAttr_Op($PurpId);
5722 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005723 my $Val = getInitVal($PurpId, $ParamTypeId);
5724 if(defined $Val) {
5725 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5726 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005727 }
5728 }
5729 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005730 if($Pos!=0 or $FType ne "Method") {
5731 $PPos += 1;
5732 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005733 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005734 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005735 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005736}
5737
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005738sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005739{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005740 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5741 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005742 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5743 return $1;
5744 }
5745 }
5746 return "";
5747}
5748
5749sub getTreeAttr_Chain($)
5750{
5751 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5752 {
5753 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5754 return $1;
5755 }
5756 }
5757 return "";
5758}
5759
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005760sub getTreeAttr_Unql($)
5761{
5762 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5763 {
5764 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5765 return $1;
5766 }
5767 }
5768 return "";
5769}
5770
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005771sub getTreeAttr_Scpe($)
5772{
5773 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5774 {
5775 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5776 return $1;
5777 }
5778 }
5779 return "";
5780}
5781
5782sub getTreeAttr_Type($)
5783{
5784 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5785 {
5786 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5787 return $1;
5788 }
5789 }
5790 return "";
5791}
5792
5793sub getTreeAttr_Name($)
5794{
5795 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5796 {
5797 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5798 return $1;
5799 }
5800 }
5801 return "";
5802}
5803
5804sub getTreeAttr_Mngl($)
5805{
5806 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5807 {
5808 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5809 return $1;
5810 }
5811 }
5812 return "";
5813}
5814
5815sub getTreeAttr_Prms($)
5816{
5817 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5818 {
5819 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5820 return $1;
5821 }
5822 }
5823 return "";
5824}
5825
5826sub getTreeAttr_Fncs($)
5827{
5828 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5829 {
5830 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5831 return $1;
5832 }
5833 }
5834 return "";
5835}
5836
5837sub getTreeAttr_Csts($)
5838{
5839 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5840 {
5841 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5842 return $1;
5843 }
5844 }
5845 return "";
5846}
5847
5848sub getTreeAttr_Purp($)
5849{
5850 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5851 {
5852 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5853 return $1;
5854 }
5855 }
5856 return "";
5857}
5858
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005859sub getTreeAttr_Op($)
5860{
5861 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5862 {
5863 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5864 return $1;
5865 }
5866 }
5867 return "";
5868}
5869
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005870sub getTreeAttr_Valu($)
5871{
5872 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5873 {
5874 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5875 return $1;
5876 }
5877 }
5878 return "";
5879}
5880
5881sub getTreeAttr_Flds($)
5882{
5883 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5884 {
5885 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5886 return $1;
5887 }
5888 }
5889 return "";
5890}
5891
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005892sub getTreeAttr_Binf($)
5893{
5894 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5895 {
5896 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5897 return $1;
5898 }
5899 }
5900 return "";
5901}
5902
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005903sub getTreeAttr_Args($)
5904{
5905 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5906 {
5907 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005908 return $1;
5909 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005910 }
5911 return "";
5912}
5913
5914sub getTreeValue($)
5915{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005916 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5917 {
5918 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5919 return $1;
5920 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005921 }
5922 return "";
5923}
5924
5925sub getTreeAccess($)
5926{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005927 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005928 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005929 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5930 {
5931 my $Access = $1;
5932 if($Access eq "prot") {
5933 return "protected";
5934 }
5935 elsif($Access eq "priv") {
5936 return "private";
5937 }
5938 }
5939 elsif($Info=~/ protected /)
5940 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005941 return "protected";
5942 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005943 elsif($Info=~/ private /)
5944 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005945 return "private";
5946 }
5947 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005948 return "public";
5949}
5950
5951sub setFuncAccess($)
5952{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005953 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005954 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005955 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005956 }
5957 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005958 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005959 }
5960}
5961
5962sub setTypeAccess($$)
5963{
5964 my ($TypeId, $TypeAttr) = @_;
5965 my $Access = getTreeAccess($TypeId);
5966 if($Access eq "protected") {
5967 $TypeAttr->{"Protected"} = 1;
5968 }
5969 elsif($Access eq "private") {
5970 $TypeAttr->{"Private"} = 1;
5971 }
5972}
5973
5974sub setFuncKind($)
5975{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005976 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5977 {
5978 if($Info=~/pseudo tmpl/) {
5979 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5980 }
5981 elsif($Info=~/ constructor /) {
5982 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5983 }
5984 elsif($Info=~/ destructor /) {
5985 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5986 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005987 }
5988}
5989
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005990sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005991{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005992 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5993 {
5994 if($Info=~/spec[ ]*:[ ]*pure /) {
5995 return "PureVirt";
5996 }
5997 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5998 return "Virt";
5999 }
6000 elsif($Info=~/ pure\s+virtual /)
6001 { # support for old GCC versions
6002 return "PureVirt";
6003 }
6004 elsif($Info=~/ virtual /)
6005 { # support for old GCC versions
6006 return "Virt";
6007 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006008 }
6009 return "";
6010}
6011
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006012sub getFuncLink($)
6013{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006014 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6015 {
6016 if($Info=~/link[ ]*:[ ]*static /) {
6017 return "Static";
6018 }
6019 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006020 return $1;
6021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006022 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006023 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006024}
6025
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006026sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006027{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006028 my ($Symbol, $LibVersion) = @_;
6029 return "" if(not $Symbol or not $LibVersion);
6030 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
6031 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006032 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006033 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
6034 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
6035 }
6036 }
6037 if($NS)
6038 {
6039 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6040 return $NS;
6041 }
6042 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006043 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006044 while($NS=~s/::[^:]+\Z//)
6045 {
6046 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6047 return $NS;
6048 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006049 }
6050 }
6051 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006052
6053 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006054}
6055
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006056sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006057{
6058 my ($TypeName, $LibVersion) = @_;
6059 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006060 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006061 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006062 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6063 return $NS;
6064 }
6065 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006066 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006067 while($NS=~s/::[^:]+\Z//)
6068 {
6069 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6070 return $NS;
6071 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006072 }
6073 }
6074 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006075 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006076}
6077
6078sub getNameSpace($)
6079{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006080 my $InfoId = $_[0];
6081 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006082 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006083 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006084 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006085 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006086 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006087 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6088 {
6089 my $NameSpace = getTreeStr($1);
6090 if($NameSpace eq "::")
6091 { # global namespace
6092 return "";
6093 }
6094 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6095 $NameSpace = $BaseNameSpace."::".$NameSpace;
6096 }
6097 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6098 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006099 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006100 else {
6101 return "";
6102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006103 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006104 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006105 { # inside data type
6106 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6107 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006108 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006109 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006110 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006111 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006112}
6113
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006114sub getEnumMembVal($)
6115{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006116 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006117 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006118 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6119 {
6120 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6121 {
6122 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6123 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6124 return getTreeValue($1);
6125 }
6126 else
6127 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6128 return getTreeValue($1);
6129 }
6130 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006131 }
6132 }
6133 return "";
6134}
6135
6136sub getSize($)
6137{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006138 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6139 {
6140 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6141 return getTreeValue($1);
6142 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006143 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006144 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006145}
6146
6147sub getAlgn($)
6148{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006149 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6150 {
6151 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6152 return $1;
6153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006154 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006155 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006156}
6157
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006158sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006159{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006160 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6161 {
6162 if($Info=~/ bitfield /) {
6163 return getSize($_[0]);
6164 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006165 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006166 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006167}
6168
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006169sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006170{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006171 if(my $Chan = getTreeAttr_Chan($_[0])) {
6172 return $Chan;
6173 }
6174 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6175 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006176 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006177 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006178}
6179
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006180sub registerHeader($$)
6181{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006182 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006183 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006184 return "";
6185 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006186 if(is_abs($Header) and not -f $Header)
6187 { # incorrect absolute path
6188 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006189 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006190 if(skipHeader($Header, $LibVersion))
6191 { # skip
6192 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006193 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006194 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6195 {
6196 detect_header_includes($Header_Path, $LibVersion);
6197
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006198 if(defined $Tolerance and $Tolerance=~/3/)
6199 { # 3 - skip headers that include non-Linux headers
6200 if($OSgroup ne "windows")
6201 {
6202 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6203 {
6204 if(specificHeader($Inc, "windows")) {
6205 return "";
6206 }
6207 }
6208 }
6209 }
6210
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006211 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6212 { # redirect
6213 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6214 or skipHeader($RHeader_Path, $LibVersion))
6215 { # skip
6216 return "";
6217 }
6218 $Header_Path = $RHeader_Path;
6219 }
6220 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6221 { # skip
6222 return "";
6223 }
6224
6225 if(my $HName = get_filename($Header_Path))
6226 { # register
6227 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6228 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6229 }
6230
6231 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6232 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006233 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006234 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006235 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006236 }
6237
6238 if($CheckHeadersOnly
6239 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6240 { # /usr/include/c++/4.6.1/...
6241 $STDCXX_TESTING = 1;
6242 }
6243
6244 return $Header_Path;
6245 }
6246 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006247}
6248
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006249sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006250{
6251 my ($Dir, $WithDeps, $LibVersion) = @_;
6252 $Dir=~s/[\/\\]+\Z//g;
6253 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006254 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006255
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006256 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006257 if($WithDeps)
6258 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006259 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6260 return;
6261 }
6262 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6263 $Mode = "DepsOnly";
6264 }
6265 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006266 else
6267 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006268 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6269 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6270 return;
6271 }
6272 }
6273 $Header_Dependency{$LibVersion}{$Dir} = 1;
6274 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6275 if($Mode eq "DepsOnly")
6276 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006277 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006278 $Header_Dependency{$LibVersion}{$Path} = 1;
6279 }
6280 return;
6281 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006282 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006283 {
6284 if($WithDeps)
6285 {
6286 my $SubDir = $Path;
6287 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6288 { # register all sub directories
6289 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6290 }
6291 }
6292 next if(is_not_header($Path));
6293 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006294 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006295 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006296 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6297 }
6298 }
6299 if(get_filename($Dir) eq "include")
6300 { # search for "lib/include/" directory
6301 my $LibDir = $Dir;
6302 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006303 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006304 }
6305 }
6306}
6307
6308sub parse_redirect($$$)
6309{
6310 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006311 my @Errors = ();
6312 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6313 push(@Errors, $1);
6314 }
6315 my $Redirect = "";
6316 foreach (@Errors)
6317 {
6318 s/\s{2,}/ /g;
6319 if(/(only|must\ include
6320 |update\ to\ include
6321 |replaced\ with
6322 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006323 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006324 {
6325 $Redirect = $2;
6326 last;
6327 }
6328 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6329 {
6330 $Redirect = $2;
6331 last;
6332 }
6333 elsif(/this\ header\ should\ not\ be\ used
6334 |programs\ should\ not\ directly\ include
6335 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6336 |is\ not\ supported\ API\ for\ general\ use
6337 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006338 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006339 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6340 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6341 }
6342 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006343 if($Redirect)
6344 {
6345 $Redirect=~s/\A<//g;
6346 $Redirect=~s/>\Z//g;
6347 }
6348 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006349}
6350
6351sub parse_includes($$)
6352{
6353 my ($Content, $Path) = @_;
6354 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006355 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006356 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006357 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006358 my $Method = substr($Header, 0, 1, "");
6359 substr($Header, length($Header)-1, 1, "");
6360 $Header = path_format($Header, $OSgroup);
6361 if($Method eq "\"" or is_abs($Header))
6362 {
6363 if(-e join_P(get_dirname($Path), $Header))
6364 { # relative path exists
6365 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006366 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006367 else
6368 { # include "..." that doesn't exist is equal to include <...>
6369 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006370 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006371 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006372 else {
6373 $Includes{$Header} = 1;
6374 }
6375 }
6376 if($ExtraInfo)
6377 {
6378 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6379 { # FT_FREETYPE_H
6380 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006381 }
6382 }
6383 return \%Includes;
6384}
6385
6386sub ignore_path($)
6387{
6388 my $Path = $_[0];
6389 if($Path=~/\~\Z/)
6390 {# skipping system backup files
6391 return 1;
6392 }
6393 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6394 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6395 return 1;
6396 }
6397 return 0;
6398}
6399
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006400sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006401{
6402 my ($ArrRef, $W) = @_;
6403 return if(length($W)<2);
6404 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6405}
6406
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006407sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006408{
6409 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006410
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006411 $H1=~s/\.[a-z]+\Z//ig;
6412 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006413
6414 my $Hname1 = get_filename($H1);
6415 my $Hname2 = get_filename($H2);
6416 my $HDir1 = get_dirname($H1);
6417 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006418 my $Dirname1 = get_filename($HDir1);
6419 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006420
6421 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6422 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6423
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006424 if($_[0] eq $_[1]
6425 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006426 return 0;
6427 }
6428 elsif($H1=~/\A\Q$H2\E/) {
6429 return 1;
6430 }
6431 elsif($H2=~/\A\Q$H1\E/) {
6432 return -1;
6433 }
6434 elsif($HDir1=~/\Q$Hname1\E/i
6435 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006436 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006437 return -1;
6438 }
6439 elsif($HDir2=~/\Q$Hname2\E/i
6440 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006441 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006442 return 1;
6443 }
6444 elsif($Hname1=~/\Q$Dirname1\E/i
6445 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006446 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006447 return -1;
6448 }
6449 elsif($Hname2=~/\Q$Dirname2\E/i
6450 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006451 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006452 return 1;
6453 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006454 elsif($Hname1=~/(config|lib|util)/i
6455 and $Hname2!~/(config|lib|util)/i)
6456 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006457 return -1;
6458 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006459 elsif($Hname2=~/(config|lib|util)/i
6460 and $Hname1!~/(config|lib|util)/i)
6461 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006462 return 1;
6463 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006464 else
6465 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006466 my $R1 = checkRelevance($H1);
6467 my $R2 = checkRelevance($H2);
6468 if($R1 and not $R2)
6469 { # libebook/e-book.h
6470 return -1;
6471 }
6472 elsif($R2 and not $R1)
6473 { # libebook/e-book.h
6474 return 1;
6475 }
6476 else
6477 {
6478 return (lc($H1) cmp lc($H2));
6479 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006480 }
6481}
6482
6483sub searchForHeaders($)
6484{
6485 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006486
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006487 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006488 registerGccHeaders();
6489
6490 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6491 { # c++ standard include paths
6492 registerCppHeaders();
6493 }
6494
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006495 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006496 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6497 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006498 {
6499 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006500 if($SystemRoot)
6501 {
6502 if(is_abs($Path)) {
6503 $Path = $SystemRoot.$Path;
6504 }
6505 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006506 if(not -e $Path) {
6507 exitStatus("Access_Error", "can't access \'$Path\'");
6508 }
6509 elsif(-f $Path) {
6510 exitStatus("Access_Error", "\'$Path\' - not a directory");
6511 }
6512 elsif(-d $Path)
6513 {
6514 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006515 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006516 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6517 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006518 }
6519 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006520 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006521 }
6522 }
6523 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006524 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006525 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6526 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006527
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006528 # registering directories
6529 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6530 {
6531 next if(not -e $Path);
6532 $Path = get_abs_path($Path);
6533 $Path = path_format($Path, $OSgroup);
6534 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006535 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006536 }
6537 elsif(-f $Path)
6538 {
6539 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006540 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006541 and not $LocalIncludes{$Dir})
6542 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006543 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006544 # if(my $OutDir = get_dirname($Dir))
6545 # { # registering the outer directory
6546 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6547 # and not $LocalIncludes{$OutDir}) {
6548 # registerDir($OutDir, 0, $LibVersion);
6549 # }
6550 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006551 }
6552 }
6553 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006554
6555 # clean memory
6556 %RegisteredDirs = ();
6557
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006558 # registering headers
6559 my $Position = 0;
6560 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6561 {
6562 if(is_abs($Dest) and not -e $Dest) {
6563 exitStatus("Access_Error", "can't access \'$Dest\'");
6564 }
6565 $Dest = path_format($Dest, $OSgroup);
6566 if(is_header($Dest, 1, $LibVersion))
6567 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006568 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006569 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6570 }
6571 }
6572 elsif(-d $Dest)
6573 {
6574 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006575 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006576 {
6577 next if(ignore_path($Path));
6578 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006579 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006580 push(@Registered, $HPath);
6581 }
6582 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006583 @Registered = sort {sortHeaders($a, $b)} @Registered;
6584 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006585 foreach my $Path (@Registered) {
6586 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6587 }
6588 }
6589 else {
6590 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6591 }
6592 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006593
6594 if(defined $Tolerance and $Tolerance=~/4/)
6595 { # 4 - skip headers included by others
6596 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6597 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006598 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006599 delete($Registered_Headers{$LibVersion}{$Path});
6600 }
6601 }
6602 }
6603
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006604 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6605 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006606 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006607 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006608 if(is_abs($Header) and not -f $Header) {
6609 exitStatus("Access_Error", "can't access file \'$Header\'");
6610 }
6611 $Header = path_format($Header, $OSgroup);
6612 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6613 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006614 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006615 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006616 }
6617 else {
6618 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6619 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006620 }
6621 }
6622 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6623 { # set relative paths (for duplicates)
6624 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6625 { # search for duplicates
6626 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6627 my $Prefix = get_dirname($FirstPath);
6628 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6629 { # detect a shortest distinguishing prefix
6630 my $NewPrefix = $1;
6631 my %Identity = ();
6632 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6633 {
6634 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6635 $Identity{$Path} = $1;
6636 }
6637 }
6638 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6639 { # all names are differend with current prefix
6640 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6641 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6642 }
6643 last;
6644 }
6645 $Prefix = $NewPrefix; # increase prefix
6646 }
6647 }
6648 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006649
6650 # clean memory
6651 %HeaderName_Paths = ();
6652
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006653 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6654 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006655 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006656 my ($Pos, $PairPos) = (-1, -1);
6657 my ($Path, $PairPath) = ();
6658 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6659 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6660 foreach my $Header_Path (@Paths)
6661 {
6662 if(get_filename($Header_Path) eq $PairName)
6663 {
6664 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6665 $PairPath = $Header_Path;
6666 }
6667 if(get_filename($Header_Path) eq $HeaderName)
6668 {
6669 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6670 $Path = $Header_Path;
6671 }
6672 }
6673 if($PairPos!=-1 and $Pos!=-1
6674 and int($PairPos)<int($Pos))
6675 {
6676 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6677 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6678 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6679 }
6680 }
6681 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6682 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6683 }
6684}
6685
6686sub detect_real_includes($$)
6687{
6688 my ($AbsPath, $LibVersion) = @_;
6689 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6690 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6691 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6692 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6693 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006694 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6695
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006696 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6697 return () if(not $Path);
6698 open(PREPROC, $Path);
6699 while(<PREPROC>)
6700 {
6701 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6702 {
6703 my $Include = path_format($1, $OSgroup);
6704 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6705 next;
6706 }
6707 if($Include eq $AbsPath) {
6708 next;
6709 }
6710 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6711 }
6712 }
6713 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006714 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6715}
6716
6717sub detect_header_includes($$)
6718{
6719 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006720 return if(not $LibVersion or not $Path);
6721 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6722 return;
6723 }
6724 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6725
6726 if(not -e $Path) {
6727 return;
6728 }
6729
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006730 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006731 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6732 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006733 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006734 {
6735 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006736 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006737 }
6738 if($RedirectPath ne $Path) {
6739 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6740 }
6741 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006742 else
6743 { # can't find
6744 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006746 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006747 if(my $Inc = parse_includes($Content, $Path))
6748 {
6749 foreach my $Include (keys(%{$Inc}))
6750 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006751 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006752
6753 if(defined $Tolerance and $Tolerance=~/4/)
6754 {
6755 if(my $HPath = identifyHeader($Include, $LibVersion))
6756 {
6757 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6758 }
6759 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006760 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006761 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006762}
6763
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006764sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006765{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006766 my $Path = $_[0];
6767 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006768 if($OStarget eq "symbian")
6769 {
6770 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6771 { # epoc32/include/libc/{stdio, ...}.h
6772 return 1;
6773 }
6774 }
6775 else
6776 {
6777 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6778 { # /usr/include/{stdio, ...}.h
6779 return 1;
6780 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006781 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006782 return 0;
6783}
6784
6785sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006786{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006787 my $Dir = $_[0];
6788 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006789 if($OStarget eq "symbian")
6790 {
6791 if(get_filename($OutDir) eq "libc"
6792 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6793 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6794 return 1;
6795 }
6796 }
6797 else
6798 { # linux
6799 if($OutDir eq "/usr/include"
6800 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6801 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6802 return 1;
6803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006804 }
6805 return 0;
6806}
6807
6808sub detect_recursive_includes($$)
6809{
6810 my ($AbsPath, $LibVersion) = @_;
6811 return () if(not $AbsPath);
6812 if(isCyclical(\@RecurInclude, $AbsPath)) {
6813 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6814 }
6815 my ($AbsDir, $Name) = separate_path($AbsPath);
6816 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006817 { # system GLIBC internals
6818 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006819 }
6820 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6821 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6822 }
6823 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006824
6825 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6826 { # skip /usr/include/c++/*/ headers
6827 return () if(not $ExtraInfo);
6828 }
6829
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006830 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006831 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006832 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006833 { # check "real" (non-"model") include paths
6834 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6835 pop(@RecurInclude);
6836 return @Paths;
6837 }
6838 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6839 detect_header_includes($AbsPath, $LibVersion);
6840 }
6841 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6842 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006843 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006844 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006845 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006846 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006847 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006848 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006849 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006850 }
6851 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006852 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006853 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006854 { # search for the nearest header
6855 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006856 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006857 if(-f $Candidate) {
6858 $HPath = $Candidate;
6859 }
6860 }
6861 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006862 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006863 }
6864 next if(not $HPath);
6865 if($HPath eq $AbsPath) {
6866 next;
6867 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006868
6869 if($Debug)
6870 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006871# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6872# {
6873# print STDERR "$AbsPath -> $HPath\n";
6874# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006875 }
6876
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006877 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6878 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006879 { # only include <...>, skip include "..." prefixes
6880 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6881 }
6882 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6883 {
6884 if($IncPath eq $AbsPath) {
6885 next;
6886 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006887 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6888 if($RIncType==-1)
6889 { # include "..."
6890 $RIncType = $IncType;
6891 }
6892 elsif($RIncType==2)
6893 {
6894 if($IncType!=-1) {
6895 $RIncType = $IncType;
6896 }
6897 }
6898 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006899 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6900 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6901 }
6902 }
6903 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6904 {
6905 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6906 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6907 { # distinguish math.h from glibc and math.h from the tested library
6908 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6909 last;
6910 }
6911 }
6912 }
6913 pop(@RecurInclude);
6914 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6915}
6916
6917sub find_in_framework($$$)
6918{
6919 my ($Header, $Framework, $LibVersion) = @_;
6920 return "" if(not $Header or not $Framework or not $LibVersion);
6921 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6922 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6923 }
6924 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6925 {
6926 if(get_filename($Dependency) eq $Framework
6927 and -f get_dirname($Dependency)."/".$Header) {
6928 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6929 }
6930 }
6931 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6932}
6933
6934sub find_in_defaults($)
6935{
6936 my $Header = $_[0];
6937 return "" if(not $Header);
6938 if(defined $Cache{"find_in_defaults"}{$Header}) {
6939 return $Cache{"find_in_defaults"}{$Header};
6940 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006941 foreach my $Dir (@DefaultIncPaths,
6942 @DefaultGccPaths,
6943 @DefaultCppPaths,
6944 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006945 {
6946 next if(not $Dir);
6947 if(-f $Dir."/".$Header) {
6948 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6949 }
6950 }
6951 return ($Cache{"find_in_defaults"}{$Header}="");
6952}
6953
6954sub cmp_paths($$)
6955{
6956 my ($Path1, $Path2) = @_;
6957 my @Parts1 = split(/[\/\\]/, $Path1);
6958 my @Parts2 = split(/[\/\\]/, $Path2);
6959 foreach my $Num (0 .. $#Parts1)
6960 {
6961 my $Part1 = $Parts1[$Num];
6962 my $Part2 = $Parts2[$Num];
6963 if($GlibcDir{$Part1}
6964 and not $GlibcDir{$Part2}) {
6965 return 1;
6966 }
6967 elsif($GlibcDir{$Part2}
6968 and not $GlibcDir{$Part1}) {
6969 return -1;
6970 }
6971 elsif($Part1=~/glib/
6972 and $Part2!~/glib/) {
6973 return 1;
6974 }
6975 elsif($Part1!~/glib/
6976 and $Part2=~/glib/) {
6977 return -1;
6978 }
6979 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6980 return $CmpRes;
6981 }
6982 }
6983 return 0;
6984}
6985
6986sub checkRelevance($)
6987{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006988 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006989 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006990
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006991 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006992 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006993 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006994
6995 my $Name = lc(get_filename($Path));
6996 my $Dir = lc(get_dirname($Path));
6997
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006998 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006999
7000 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007001 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007002 my $Len = length($Token);
7003 next if($Len<=1);
7004 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
7005 { # include/evolution-data-server-1.4/libebook/e-book.h
7006 return 1;
7007 }
7008 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007009 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007010 return 1;
7011 }
7012 }
7013 return 0;
7014}
7015
7016sub checkFamily(@)
7017{
7018 my @Paths = @_;
7019 return 1 if($#Paths<=0);
7020 my %Prefix = ();
7021 foreach my $Path (@Paths)
7022 {
7023 if($SystemRoot) {
7024 $Path = cut_path_prefix($Path, $SystemRoot);
7025 }
7026 if(my $Dir = get_dirname($Path))
7027 {
7028 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
7029 $Prefix{$Dir} += 1;
7030 $Prefix{get_dirname($Dir)} += 1;
7031 }
7032 }
7033 foreach (sort keys(%Prefix))
7034 {
7035 if(get_depth($_)>=3
7036 and $Prefix{$_}==$#Paths+1) {
7037 return 1;
7038 }
7039 }
7040 return 0;
7041}
7042
7043sub isAcceptable($$$)
7044{
7045 my ($Header, $Candidate, $LibVersion) = @_;
7046 my $HName = get_filename($Header);
7047 if(get_dirname($Header))
7048 { # with prefix
7049 return 1;
7050 }
7051 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
7052 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
7053 return 1;
7054 }
7055 if(checkRelevance($Candidate))
7056 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
7057 return 1;
7058 }
7059 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
7060 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
7061 # /usr/include/qt4/Qt/qsslconfiguration.h
7062 return 1;
7063 }
7064 if($OStarget eq "symbian")
7065 {
7066 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
7067 return 1;
7068 }
7069 }
7070 return 0;
7071}
7072
7073sub isRelevant($$$)
7074{ # disallow to search for "abstract" headers in too deep directories
7075 my ($Header, $Candidate, $LibVersion) = @_;
7076 my $HName = get_filename($Header);
7077 if($OStarget eq "symbian")
7078 {
7079 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7080 return 0;
7081 }
7082 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007083 if($OStarget ne "bsd")
7084 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007085 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7086 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7087 return 0;
7088 }
7089 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007090 if($OStarget ne "windows")
7091 {
7092 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7093 { # skip /usr/include/wine/msvcrt
7094 return 0;
7095 }
7096 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007097 if(not get_dirname($Header)
7098 and $Candidate=~/[\/\\]wx[\/\\]/)
7099 { # do NOT search in system /wx/ directory
7100 # for headers without a prefix: sstream.h
7101 return 0;
7102 }
7103 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7104 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7105 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7106 return 0;
7107 }
7108 if($Candidate=~/[\/\\]asm-/
7109 and (my $Arch = getArch($LibVersion)) ne "unknown")
7110 { # arch-specific header files
7111 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7112 {# skip ../asm-arm/ if using x86 architecture
7113 return 0;
7114 }
7115 }
7116 my @Candidates = getSystemHeaders($HName, $LibVersion);
7117 if($#Candidates==1)
7118 { # unique header
7119 return 1;
7120 }
7121 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7122 if($#SCandidates==1)
7123 { # unique name
7124 return 1;
7125 }
7126 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7127 if(get_depth($Candidate)-$SystemDepth>=5)
7128 { # abstract headers in too deep directories
7129 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7130 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7131 return 0;
7132 }
7133 }
7134 if($Header eq "parser.h"
7135 and $Candidate!~/\/libxml2\//)
7136 { # select parser.h from xml2 library
7137 return 0;
7138 }
7139 if(not get_dirname($Header)
7140 and keys(%{$SystemHeaders{$HName}})>=3)
7141 { # many headers with the same name
7142 # like thread.h included without a prefix
7143 if(not checkFamily(@Candidates)) {
7144 return 0;
7145 }
7146 }
7147 return 1;
7148}
7149
7150sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007151{ # cache function
7152 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7153 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7154 }
7155 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7156}
7157
7158sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007159{
7160 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007161 if(-f $Header) {
7162 return $Header;
7163 }
7164 if(is_abs($Header) and not -f $Header)
7165 { # incorrect absolute path
7166 return "";
7167 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007168 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007169 { # too abstract configuration headers
7170 return "";
7171 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007172 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007173 if($OSgroup ne "windows")
7174 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007175 if(defined $WinHeaders{lc($HName)}
7176 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007177 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007178 return "";
7179 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007180 }
7181 if($OSgroup ne "macos")
7182 {
7183 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007184 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007185 return "";
7186 }
7187 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007188
7189 if(defined $ObsoleteHeaders{$HName})
7190 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007191 return "";
7192 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007193 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7194 {
7195 if(defined $AlienHeaders{$HName}
7196 or defined $AlienHeaders{$Header})
7197 { # alien headers from other systems
7198 return "";
7199 }
7200 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007201
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007202 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007203 { # search in default paths
7204 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007205 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007206 }
7207 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007208 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007209 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007210 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007211 }
7212 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7213 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7214 {
7215 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007216 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007217 }
7218 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007219 # error
7220 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007221}
7222
7223sub getSystemHeaders($$)
7224{
7225 my ($Header, $LibVersion) = @_;
7226 my @Candidates = ();
7227 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7228 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007229 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007230 next;
7231 }
7232 push(@Candidates, $Candidate);
7233 }
7234 return @Candidates;
7235}
7236
7237sub cut_path_prefix($$)
7238{
7239 my ($Path, $Prefix) = @_;
7240 return $Path if(not $Prefix);
7241 $Prefix=~s/[\/\\]+\Z//;
7242 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7243 return $Path;
7244}
7245
7246sub is_default_include_dir($)
7247{
7248 my $Dir = $_[0];
7249 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007250 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007251}
7252
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007253sub identifyHeader($$)
7254{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007255 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007256 if(not $Header) {
7257 return "";
7258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007259 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007260 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7261 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007262 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007263 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007264}
7265
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007266sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007267{ # search for header by absolute path, relative path or name
7268 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007269 if(-f $Header)
7270 { # it's relative or absolute path
7271 return get_abs_path($Header);
7272 }
7273 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7274 and my $HeaderDir = find_in_defaults($Header))
7275 { # search for libc headers in the /usr/include
7276 # for non-libc target library before searching
7277 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007278 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007279 }
7280 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7281 { # search in the target library paths
7282 return $Path;
7283 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007284 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007285 { # search in the internal GCC include paths
7286 return $DefaultGccHeader{$Header};
7287 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007288 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007289 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007290 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007291 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007292 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007293 { # search in the default G++ include paths
7294 return $DefaultCppHeader{$Header};
7295 }
7296 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7297 { # search everywhere in the system
7298 return $AnyPath;
7299 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007300 elsif($OSgroup eq "macos")
7301 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7302 if(my $Dir = get_dirname($Header))
7303 {
7304 my $RelPath = "Headers\/".get_filename($Header);
7305 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007306 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007307 }
7308 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007309 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007310 # cannot find anything
7311 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007312}
7313
7314sub getLocation($)
7315{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007316 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7317 {
7318 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007319 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007320 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007321 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007322 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007323}
7324
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007325sub getNameByInfo($)
7326{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007327 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007328 {
7329 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7330 {
7331 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7332 {
7333 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7334 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007335 my $Str = $1;
7336 if($CppMode{$Version}
7337 and $Str=~/\Ac99_(.+)\Z/)
7338 {
7339 if($CppKeywords_A{$1}) {
7340 $Str=$1;
7341 }
7342 }
7343 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007344 }
7345 }
7346 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007347 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007348 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007349}
7350
7351sub getTreeStr($)
7352{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007353 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007354 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007355 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7356 {
7357 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007358 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007359 and $Str=~/\Ac99_(.+)\Z/)
7360 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007361 if($CppKeywords_A{$1}) {
7362 $Str=$1;
7363 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007364 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007365 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007366 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007367 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007368 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007369}
7370
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007371sub getFuncShortName($)
7372{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007373 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007374 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007375 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007376 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007377 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007378 {
7379 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7380 {
7381 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7382 return "operator ".$RName;
7383 }
7384 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007385 }
7386 else
7387 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007388 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7389 {
7390 if(my $Ind = $Operator_Indication{$1}) {
7391 return "operator".$Ind;
7392 }
7393 elsif(not $UnknownOperator{$1})
7394 {
7395 printMsg("WARNING", "unknown operator $1");
7396 $UnknownOperator{$1} = 1;
7397 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007398 }
7399 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007400 }
7401 else
7402 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007403 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7404 return getTreeStr($1);
7405 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007406 }
7407 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007408 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007409}
7410
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007411sub getFuncReturn($)
7412{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007413 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7414 {
7415 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7416 {
7417 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7418 return $1;
7419 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007420 }
7421 }
7422 return "";
7423}
7424
7425sub getFuncOrig($)
7426{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007427 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7428 {
7429 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7430 return $1;
7431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007432 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007433 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007434}
7435
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007436sub unmangleArray(@)
7437{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007438 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007439 { # MSVC mangling
7440 my $UndNameCmd = get_CmdPath("undname");
7441 if(not $UndNameCmd) {
7442 exitStatus("Not_Found", "can't find \"undname\"");
7443 }
7444 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007445 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007446 }
7447 else
7448 { # GCC mangling
7449 my $CppFiltCmd = get_CmdPath("c++filt");
7450 if(not $CppFiltCmd) {
7451 exitStatus("Not_Found", "can't find c++filt in PATH");
7452 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007453 if(not defined $CPPFILT_SUPPORT_FILE)
7454 {
7455 my $Info = `$CppFiltCmd -h 2>&1`;
7456 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7457 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007458 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007459 if($CPPFILT_SUPPORT_FILE)
7460 { # new versions of c++filt can take a file
7461 if($#_>$MAX_CPPFILT_FILE_SIZE)
7462 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7463 # this is fixed in the oncoming version of Binutils
7464 my @Half = splice(@_, 0, ($#_+1)/2);
7465 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007466 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007467 else
7468 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007469 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7470 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7471 if($?==139)
7472 { # segmentation fault
7473 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7474 }
7475 return split(/\n/, $Res);
7476 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007477 }
7478 else
7479 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007480 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7481 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007482 my @Half = splice(@_, 0, ($#_+1)/2);
7483 return (unmangleArray(@Half), unmangleArray(@_))
7484 }
7485 else
7486 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007487 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007488 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7489 if($?==139)
7490 { # segmentation fault
7491 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7492 }
7493 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007494 }
7495 }
7496 }
7497}
7498
7499sub get_SignatureNoInfo($$)
7500{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007501 my ($Symbol, $LibVersion) = @_;
7502 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
7503 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007504 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007505 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007506 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007507 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007508 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04007509 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007510 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
7511 $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;
7512 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007513 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007514 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007515 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007516 $Signature .= " [data]";
7517 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007518 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007519 $Signature .= " (...)";
7520 }
7521 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007522 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007523 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04007524 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007525 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
7526 }
7527 if($SymbolVersion) {
7528 $Signature .= $VersionSpec.$SymbolVersion;
7529 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007530 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007531}
7532
7533sub get_ChargeLevel($$)
7534{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007535 my ($Symbol, $LibVersion) = @_;
7536 return "" if($Symbol!~/\A(_Z|\?)/);
7537 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7538 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007539 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007540 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007541 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007542 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007543 return "[in-charge]";
7544 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007545 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007546 return "[not-in-charge]";
7547 }
7548 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007549 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007550 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007551 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007552 return "[in-charge]";
7553 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007554 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007555 return "[not-in-charge]";
7556 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007557 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007558 return "[in-charge-deleting]";
7559 }
7560 }
7561 }
7562 else
7563 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007564 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007565 return "[in-charge]";
7566 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007567 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007568 return "[not-in-charge]";
7569 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007570 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007571 return "[in-charge]";
7572 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007573 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007574 return "[not-in-charge]";
7575 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007576 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007577 return "[in-charge-deleting]";
7578 }
7579 }
7580 return "";
7581}
7582
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007583sub get_Signature_M($$)
7584{
7585 my ($Symbol, $LibVersion) = @_;
7586 my $Signature_M = $tr_name{$Symbol};
7587 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7588 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007589 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007590 }
7591 return $Signature_M;
7592}
7593
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007594sub get_Signature($$)
7595{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007596 my ($Symbol, $LibVersion) = @_;
7597 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7598 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007599 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007600 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
7601 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007602 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007603 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007604 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007605 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007606 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7607 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007608 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007609 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7610 {
7611 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7612 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7613 $Signature .= "~";
7614 }
7615 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007616 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007617 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007618 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007619 }
7620 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007621 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007622 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007623 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7624 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007625 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007626 else
7627 {
7628 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007629 }
7630 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007631 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007632 {
7633 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007634 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007635 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007636 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007637 if(not $ParamTypeName) {
7638 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7639 }
7640 foreach my $Typedef (keys(%ChangedTypedef))
7641 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007642 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7643 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7644 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007645 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007646 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7647 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007648 if($ParamName eq "this"
7649 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007650 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007651 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007652 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007653 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007654 }
7655 else {
7656 push(@ParamArray, $ParamTypeName);
7657 }
7658 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007659 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7660 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007661 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007662 }
7663 else
7664 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007665 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007666 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007667 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007668 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007669 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007670 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7671 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007672 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007673 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007674 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7675 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007676 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007677 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007678 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7679 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007680 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007681 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007682 }
7683 }
7684 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007685 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007686 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007687 }
7688 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007689 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007690 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007691 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007692}
7693
7694sub create_member_decl($$)
7695{
7696 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007697 if($TName=~/\([\*]+\)/)
7698 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007699 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7700 return $TName;
7701 }
7702 else
7703 {
7704 my @ArraySizes = ();
7705 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7706 push(@ArraySizes, $1);
7707 }
7708 return $TName." ".$Member.join("", @ArraySizes);
7709 }
7710}
7711
7712sub getFuncType($)
7713{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007714 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7715 {
7716 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7717 {
7718 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7719 {
7720 if($Type eq "method_type") {
7721 return "Method";
7722 }
7723 elsif($Type eq "function_type") {
7724 return "Function";
7725 }
7726 else {
7727 return "Other";
7728 }
7729 }
7730 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007731 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007732 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007733}
7734
7735sub getFuncTypeId($)
7736{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007737 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7738 {
7739 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7740 return $1;
7741 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007742 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007743 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007744}
7745
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007746sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007747{ # "._N" or "$_N" in older GCC versions
7748 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007749}
7750
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007751sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007752{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007753 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7754 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007755 }
7756
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007757 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007758
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007759 if($_[1] ne "S")
7760 {
7761 $N=~s/\A[ ]+//g;
7762 $N=~s/[ ]+\Z//g;
7763 $N=~s/[ ]{2,}/ /g;
7764 }
7765
7766 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007767
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007768 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007769
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007770 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7771 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007772
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007773 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007774
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007775 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007776
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007777 if($_[1] eq "S")
7778 {
7779 if(index($N, "operator")!=-1) {
7780 $N=~s/\b(operator[ ]*)> >/$1>>/;
7781 }
7782 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007783
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007784 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007785}
7786
7787sub get_HeaderDeps($$)
7788{
7789 my ($AbsPath, $LibVersion) = @_;
7790 return () if(not $AbsPath or not $LibVersion);
7791 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7792 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7793 }
7794 my %IncDir = ();
7795 detect_recursive_includes($AbsPath, $LibVersion);
7796 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7797 {
7798 next if(not $HeaderPath);
7799 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7800 my $Dir = get_dirname($HeaderPath);
7801 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7802 {
7803 my $Dep = $Dir;
7804 if($Prefix)
7805 {
7806 if($OSgroup eq "windows")
7807 { # case insensitive seach on windows
7808 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7809 next;
7810 }
7811 }
7812 elsif($OSgroup eq "macos")
7813 { # seach in frameworks
7814 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7815 {
7816 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7817 {# frameworks
7818 my ($HFramework, $HName) = ($1, $2);
7819 $Dep = $HFramework;
7820 }
7821 else
7822 {# mismatch
7823 next;
7824 }
7825 }
7826 }
7827 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7828 { # Linux, FreeBSD
7829 next;
7830 }
7831 }
7832 if(not $Dep)
7833 { # nothing to include
7834 next;
7835 }
7836 if(is_default_include_dir($Dep))
7837 { # included by the compiler
7838 next;
7839 }
7840 if(get_depth($Dep)==1)
7841 { # too short
7842 next;
7843 }
7844 if(isLibcDir($Dep))
7845 { # do NOT include /usr/include/{sys,bits}
7846 next;
7847 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007848 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007849 }
7850 }
7851 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7852 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7853}
7854
7855sub sortIncPaths($$)
7856{
7857 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007858 if(not $ArrRef or $#{$ArrRef}<0) {
7859 return $ArrRef;
7860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007861 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7862 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007863 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007864 return $ArrRef;
7865}
7866
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007867sub sortDeps($$$)
7868{
7869 if($Header_Dependency{$_[2]}{$_[0]}
7870 and not $Header_Dependency{$_[2]}{$_[1]}) {
7871 return 1;
7872 }
7873 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7874 and $Header_Dependency{$_[2]}{$_[1]}) {
7875 return -1;
7876 }
7877 return 0;
7878}
7879
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007880sub join_P($$)
7881{
7882 my $S = "/";
7883 if($OSgroup eq "windows") {
7884 $S = "\\";
7885 }
7886 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007887}
7888
7889sub get_namespace_additions($)
7890{
7891 my $NameSpaces = $_[0];
7892 my ($Additions, $AddNameSpaceId) = ("", 1);
7893 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7894 {
7895 next if($SkipNameSpaces{$Version}{$NS});
7896 next if(not $NS or $NameSpaces->{$NS}==-1);
7897 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7898 next if($NS=~/\A__/i);
7899 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007900 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007901 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7902 my @NS_Parts = split(/::/, $NS);
7903 next if($#NS_Parts==-1);
7904 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7905 foreach my $NS_Part (@NS_Parts)
7906 {
7907 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7908 $TypeDecl_Suffix .= "}";
7909 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007910 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007911 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7912 $Additions.=" $TypeDecl\n $FuncDecl\n";
7913 $AddNameSpaceId+=1;
7914 }
7915 return $Additions;
7916}
7917
7918sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007919{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007920 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007921 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007922 if($Fmt eq "windows")
7923 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007924 $Path=~s/\//\\/g;
7925 $Path=lc($Path);
7926 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007927 else
7928 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007929 $Path=~s/\\/\//g;
7930 }
7931 return $Path;
7932}
7933
7934sub inc_opt($$)
7935{
7936 my ($Path, $Style) = @_;
7937 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007938 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007939 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007940 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007941 return "-I\"".path_format($Path, "unix")."\"";
7942 }
7943 elsif($OSgroup eq "macos"
7944 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007945 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007946 return "-F".esc(get_dirname($Path));
7947 }
7948 else {
7949 return "-I".esc($Path);
7950 }
7951 }
7952 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007953 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007954 }
7955 return "";
7956}
7957
7958sub platformSpecs($)
7959{
7960 my $LibVersion = $_[0];
7961 my $Arch = getArch($LibVersion);
7962 if($OStarget eq "symbian")
7963 { # options for GCCE compiler
7964 my %Symbian_Opts = map {$_=>1} (
7965 "-D__GCCE__",
7966 "-DUNICODE",
7967 "-fexceptions",
7968 "-D__SYMBIAN32__",
7969 "-D__MARM_INTERWORK__",
7970 "-D_UNICODE",
7971 "-D__S60_50__",
7972 "-D__S60_3X__",
7973 "-D__SERIES60_3X__",
7974 "-D__EPOC32__",
7975 "-D__MARM__",
7976 "-D__EABI__",
7977 "-D__MARM_ARMV5__",
7978 "-D__SUPPORT_CPP_EXCEPTIONS__",
7979 "-march=armv5t",
7980 "-mapcs",
7981 "-mthumb-interwork",
7982 "-DEKA2",
7983 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7984 );
7985 return join(" ", keys(%Symbian_Opts));
7986 }
7987 elsif($OSgroup eq "windows"
7988 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7989 { # add options to MinGW compiler
7990 # to simulate the MSVC compiler
7991 my %MinGW_Opts = map {$_=>1} (
7992 "-D_WIN32",
7993 "-D_STDCALL_SUPPORTED",
7994 "-D__int64=\"long long\"",
7995 "-D__int32=int",
7996 "-D__int16=short",
7997 "-D__int8=char",
7998 "-D__possibly_notnullterminated=\" \"",
7999 "-D__nullterminated=\" \"",
8000 "-D__nullnullterminated=\" \"",
8001 "-D__w64=\" \"",
8002 "-D__ptr32=\" \"",
8003 "-D__ptr64=\" \"",
8004 "-D__forceinline=inline",
8005 "-D__inline=inline",
8006 "-D__uuidof(x)=IID()",
8007 "-D__try=",
8008 "-D__except(x)=",
8009 "-D__declspec(x)=__attribute__((x))",
8010 "-D__pragma(x)=",
8011 "-D_inline=inline",
8012 "-D__forceinline=__inline",
8013 "-D__stdcall=__attribute__((__stdcall__))",
8014 "-D__cdecl=__attribute__((__cdecl__))",
8015 "-D__fastcall=__attribute__((__fastcall__))",
8016 "-D__thiscall=__attribute__((__thiscall__))",
8017 "-D_stdcall=__attribute__((__stdcall__))",
8018 "-D_cdecl=__attribute__((__cdecl__))",
8019 "-D_fastcall=__attribute__((__fastcall__))",
8020 "-D_thiscall=__attribute__((__thiscall__))",
8021 "-DSHSTDAPI_(x)=x",
8022 "-D_MSC_EXTENSIONS",
8023 "-DSECURITY_WIN32",
8024 "-D_MSC_VER=1500",
8025 "-D_USE_DECLSPECS_FOR_SAL",
8026 "-D__noop=\" \"",
8027 "-DDECLSPEC_DEPRECATED=\" \"",
8028 "-D__builtin_alignof(x)=__alignof__(x)",
8029 "-DSORTPP_PASS");
8030 if($Arch eq "x86") {
8031 $MinGW_Opts{"-D_M_IX86=300"}=1;
8032 }
8033 elsif($Arch eq "x86_64") {
8034 $MinGW_Opts{"-D_M_AMD64=300"}=1;
8035 }
8036 elsif($Arch eq "ia64") {
8037 $MinGW_Opts{"-D_M_IA64=300"}=1;
8038 }
8039 return join(" ", keys(%MinGW_Opts));
8040 }
8041 return "";
8042}
8043
8044my %C_Structure = map {$_=>1} (
8045# FIXME: Can't separate union and struct data types before dumping,
8046# so it sometimes cause compilation errors for unknown reason
8047# when trying to declare TYPE* tmp_add_class_N
8048# This is a list of such structures + list of other C structures
8049 "sigval",
8050 "sigevent",
8051 "sigaction",
8052 "sigvec",
8053 "sigstack",
8054 "timeval",
8055 "timezone",
8056 "rusage",
8057 "rlimit",
8058 "wait",
8059 "flock",
8060 "stat",
8061 "_stat",
8062 "stat32",
8063 "_stat32",
8064 "stat64",
8065 "_stat64",
8066 "_stati64",
8067 "if_nameindex",
8068 "usb_device",
8069 "sigaltstack",
8070 "sysinfo",
8071 "timeLocale",
8072 "tcp_debug",
8073 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008074 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008075 "timespec",
8076 "random_data",
8077 "drand48_data",
8078 "_IO_marker",
8079 "_IO_FILE",
8080 "lconv",
8081 "sched_param",
8082 "tm",
8083 "itimerspec",
8084 "_pthread_cleanup_buffer",
8085 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008086 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008087 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008088 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008089 "sigcontext",
8090 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008091 # Mac
8092 "_timex",
8093 "_class_t",
8094 "_category_t",
8095 "_class_ro_t",
8096 "_protocol_t",
8097 "_message_ref_t",
8098 "_super_message_ref_t",
8099 "_ivar_t",
8100 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008101);
8102
8103sub getCompileCmd($$$)
8104{
8105 my ($Path, $Opt, $Inc) = @_;
8106 my $GccCall = $GCC_PATH;
8107 if($Opt) {
8108 $GccCall .= " ".$Opt;
8109 }
8110 $GccCall .= " -x ";
8111 if($OSgroup eq "macos") {
8112 $GccCall .= "objective-";
8113 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008114
8115 if($EMERGENCY_MODE_48)
8116 { # workaround for GCC 4.8 (C only)
8117 $GccCall .= "c++";
8118 }
8119 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008120 { # compile as "C++" header
8121 # to obtain complete dump using GCC 4.0
8122 $GccCall .= "c++-header";
8123 }
8124 else
8125 { # compile as "C++" source
8126 # GCC 3.3 cannot compile headers
8127 $GccCall .= "c++";
8128 }
8129 if(my $Opts = platformSpecs($Version))
8130 {# platform-specific options
8131 $GccCall .= " ".$Opts;
8132 }
8133 # allow extra qualifications
8134 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008135 $GccCall .= " -fpermissive";
8136 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008137 if($NoStdInc)
8138 {
8139 $GccCall .= " -nostdinc";
8140 $GccCall .= " -nostdinc++";
8141 }
8142 if($CompilerOptions{$Version})
8143 { # user-defined options
8144 $GccCall .= " ".$CompilerOptions{$Version};
8145 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008146 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008147 if($Inc)
8148 { # include paths
8149 $GccCall .= " ".$Inc;
8150 }
8151 return $GccCall;
8152}
8153
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008154sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008155{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008156 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008157 my %HeaderElems = (
8158 # Types
8159 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008160 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008161 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8162 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008163 "time.h" => ["time_t"],
8164 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008165 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8166 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008167 "stdbool.h" => ["_Bool"],
8168 "rpc/xdr.h" => ["bool_t"],
8169 "in_systm.h" => ["n_long", "n_short"],
8170 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008171 "arpa/inet.h" => ["fw_src", "ip_src"],
8172 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008173 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008174 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008175 );
8176 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008177 foreach (keys(%HeaderElems))
8178 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008179 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008180 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008181 }
8182 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008183 my %Types = ();
8184 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8185 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008186 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008187 }
8188 if(keys(%Types))
8189 {
8190 my %AddHeaders = ();
8191 foreach my $Type (keys(%Types))
8192 {
8193 if(my $Header = $AutoPreamble{$Type})
8194 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008195 if(my $Path = identifyHeader($Header, $LibVersion))
8196 {
8197 if(skipHeader($Path, $LibVersion)) {
8198 next;
8199 }
8200 $Path = path_format($Path, $OSgroup);
8201 $AddHeaders{$Path}{"Type"} = $Type;
8202 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008203 }
8204 }
8205 }
8206 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008207 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008208 }
8209 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008210 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008211}
8212
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008213sub checkCTags($)
8214{
8215 my $Path = $_[0];
8216 if(not $Path) {
8217 return;
8218 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008219 my $CTags = undef;
8220
8221 if($OSgroup eq "bsd")
8222 { # use ectags on BSD
8223 $CTags = get_CmdPath("ectags");
8224 if(not $CTags) {
8225 printMsg("WARNING", "can't find \'ectags\' program");
8226 }
8227 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008228 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008229 $CTags = get_CmdPath("ctags");
8230 }
8231 if(not $CTags)
8232 {
8233 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008234 return;
8235 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008236
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008237 if($OSgroup ne "linux")
8238 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008239 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8240 if($Info!~/exuberant/i)
8241 {
8242 printMsg("WARNING", "incompatible version of \'ctags\' program");
8243 return;
8244 }
8245 }
8246
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008247 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008248 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008249 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008250 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008251 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008252 open(CTAGS, "<", $Out);
8253 while(my $Line = <CTAGS>)
8254 {
8255 chomp($Line);
8256 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008257 if(defined $Intrinsic_Keywords{$Name})
8258 { # noise
8259 next;
8260 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008261 if($Type eq "n")
8262 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008263 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008264 next;
8265 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008266 if(index($Scpe, "struct:")==0) {
8267 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008268 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008269 if(index($Scpe, "namespace:")==0)
8270 {
8271 if($Scpe=~s/\Anamespace://) {
8272 $Name = $Scpe."::".$Name;
8273 }
8274 }
8275 $TUnit_NameSpaces{$Version}{$Name} = 1;
8276 }
8277 elsif($Type eq "p")
8278 {
8279 if(not $Scpe or index($Scpe, "namespace:")==0) {
8280 $TUnit_Funcs{$Version}{$Name} = 1;
8281 }
8282 }
8283 elsif($Type eq "x")
8284 {
8285 if(not $Scpe or index($Scpe, "namespace:")==0) {
8286 $TUnit_Vars{$Version}{$Name} = 1;
8287 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008288 }
8289 }
8290 close(CTAGS);
8291}
8292
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008293sub preChange($$)
8294{
8295 my ($HeaderPath, $IncStr) = @_;
8296
8297 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8298 my $Content = undef;
8299
8300 if($OStarget eq "windows"
8301 and get_dumpmachine($GCC_PATH)=~/mingw/i
8302 and $MinGWMode{$Version}!=-1)
8303 { # modify headers to compile by MinGW
8304 if(not $Content)
8305 { # preprocessing
8306 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8307 }
8308 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8309 { # __asm { ... }
8310 $MinGWMode{$Version}=1;
8311 }
8312 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8313 { # comments after preprocessing
8314 $MinGWMode{$Version}=1;
8315 }
8316 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8317 { # 0xffui8
8318 $MinGWMode{$Version}=1;
8319 }
8320
8321 if($MinGWMode{$Version}) {
8322 printMsg("INFO", "Using MinGW compatibility mode");
8323 }
8324 }
8325
8326 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8327 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8328 { # rename C++ keywords in C code
8329 # disable this code by -cpp-compatible option
8330 if(not $Content)
8331 { # preprocessing
8332 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8333 }
8334 my $RegExp_C = join("|", keys(%CppKeywords_C));
8335 my $RegExp_F = join("|", keys(%CppKeywords_F));
8336 my $RegExp_O = join("|", keys(%CppKeywords_O));
8337
8338 my $Detected = undef;
8339
8340 while($Content=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*(\,|\)|\;|\-\>|\.|\:\s*\d))/$1$2c99_$3$4/g)
8341 { # MATCH:
8342 # int foo(int new, int class, int (*new)(int));
8343 # unsigned private: 8;
8344 # DO NOT MATCH:
8345 # #pragma GCC visibility push(default)
8346 $CppMode{$Version} = 1;
8347 $Detected = "$1$2$3$4" if(not defined $Detected);
8348 }
8349 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8350 { # MATCH:
8351 # int delete(...);
8352 # int explicit(...);
8353 # DO NOT MATCH:
8354 # void operator delete(...)
8355 $CppMode{$Version} = 1;
8356 $Detected = "$1$2$3" if(not defined $Detected);
8357 }
8358 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8359 { # MATCH:
8360 # int bool;
8361 # DO NOT MATCH:
8362 # bool X;
8363 # return *this;
8364 # throw;
8365 $CppMode{$Version} = 1;
8366 $Detected = "$1$2$3" if(not defined $Detected);
8367 }
8368 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8369 { # MATCH:
8370 # int operator(...);
8371 # DO NOT MATCH:
8372 # int operator()(...);
8373 $CppMode{$Version} = 1;
8374 $Detected = "$1$2$3" if(not defined $Detected);
8375 }
8376 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8377 { # MATCH:
8378 # int foo(int operator);
8379 # int foo(int operator, int other);
8380 # DO NOT MATCH:
8381 # int operator,(...);
8382 $CppMode{$Version} = 1;
8383 $Detected = "$1$2$3" if(not defined $Detected);
8384 }
8385 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8386 { # MATCH:
8387 # int foo(gboolean *bool);
8388 # DO NOT MATCH:
8389 # void setTabEnabled(int index, bool);
8390 $CppMode{$Version} = 1;
8391 $Detected = "$1$2$3" if(not defined $Detected);
8392 }
8393 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8394 { # MATCH:
8395 # int foo(int* this);
8396 # int bar(int this);
8397 # int baz(int throw);
8398 # DO NOT MATCH:
8399 # foo(X, this);
8400 $CppMode{$Version} = 1;
8401 $Detected = "$1$2$3$4" if(not defined $Detected);
8402 }
8403 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8404 { # MATCH:
8405 # struct template {...};
8406 # extern template foo(...);
8407 $CppMode{$Version} = 1;
8408 $Detected = "$1$2" if(not defined $Detected);
8409 }
8410
8411 if($CppMode{$Version} == 1)
8412 {
8413 if($Debug)
8414 {
8415 $Detected=~s/\A\s+//g;
8416 printMsg("INFO", "Detected code: \"$Detected\"");
8417 }
8418 }
8419
8420 # remove typedef enum NAME NAME;
8421 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8422 my $N = 0;
8423 while($N<=$#FwdTypedefs-1)
8424 {
8425 my $S = $FwdTypedefs[$N];
8426 if($S eq $FwdTypedefs[$N+1])
8427 {
8428 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008429 $CppMode{$Version} = 1;
8430
8431 if($Debug) {
8432 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8433 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008434 }
8435 $N+=2;
8436 }
8437
8438 if($CppMode{$Version}==1) {
8439 printMsg("INFO", "Using C++ compatibility mode");
8440 }
8441 }
8442
8443 if($CppMode{$Version}==1
8444 or $MinGWMode{$Version}==1)
8445 {
8446 my $IPath = $TMP_DIR."/dump$Version.i";
8447 writeFile($IPath, $Content);
8448 return $IPath;
8449 }
8450
8451 return undef;
8452}
8453
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008454sub getDump()
8455{
8456 if(not $GCC_PATH) {
8457 exitStatus("Error", "internal error - GCC path is not set");
8458 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008459
8460 my @Headers = keys(%{$Registered_Headers{$Version}});
8461 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8462
8463 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8464
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008465 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008466 my $HeaderPath = $TmpHeaderPath;
8467
8468 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008469 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008470 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8471 {
8472 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008473 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008474 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008475 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008476 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8477 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008478 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008479 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008480 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008481 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8482 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8483 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008484 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008485 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008486
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008487 if($ExtraInfo)
8488 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008489 if($IncludeString) {
8490 writeFile($ExtraInfo."/include-string", $IncludeString);
8491 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008492 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8493 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008494
8495 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8496 {
8497 my $REDIR = "";
8498 foreach my $P1 (sort @Redirects) {
8499 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8500 }
8501 writeFile($ExtraInfo."/include-redirect", $REDIR);
8502 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008503 }
8504
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008505 if(not keys(%{$TargetHeaders{$Version}}))
8506 { # Target headers
8507 addTargetHeaders($Version);
8508 }
8509
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008510 # clean memory
8511 %RecursiveIncludes = ();
8512 %Header_Include_Prefix = ();
8513 %Header_Includes = ();
8514
8515 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008516 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008517 delete($Cache{"detect_header_includes"});
8518 delete($Cache{"selectSystemHeader"});
8519
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008520 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008521 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8522 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008523
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008524 if($ExtraInfo)
8525 { # extra information for other tools
8526 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8527 }
8528
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008529 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008530 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008531 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008532
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008533 if($COMMON_LANGUAGE{$Version} eq "C++") {
8534 checkCTags($Pre);
8535 }
8536
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008537 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8538 { # try to correct the preprocessor output
8539 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008540 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008541
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008542 if($COMMON_LANGUAGE{$Version} eq "C++")
8543 { # add classes and namespaces to the dump
8544 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008545 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008546 or $MinGWMode{$Version}==1) {
8547 $CHdump .= " -fpreprocessed";
8548 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008549 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008550 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008551 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008552 chdir($ORIG_DIR);
8553 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8554 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008555 my $Content = readFile($ClassDump);
8556 foreach my $ClassInfo (split(/\n\n/, $Content))
8557 {
8558 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8559 {
8560 my $CName = $1;
8561 next if($CName=~/\A(__|_objc_|_opaque_)/);
8562 $TUnit_NameSpaces{$Version}{$CName} = -1;
8563 if($CName=~/\A[\w:]+\Z/)
8564 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008565 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008566 }
8567 if($CName=~/(\w[\w:]*)::/)
8568 { # namespaces
8569 my $NS = $1;
8570 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8571 $TUnit_NameSpaces{$Version}{$NS} = 1;
8572 }
8573 }
8574 }
8575 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8576 { # read v-tables (advanced approach)
8577 my ($CName, $VTable) = ($1, $2);
8578 $ClassVTable_Content{$Version}{$CName} = $VTable;
8579 }
8580 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008581 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8582 { # add user-defined namespaces
8583 $TUnit_NameSpaces{$Version}{$NS} = 1;
8584 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008585 if($Debug)
8586 { # debug mode
8587 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008588 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008589 }
8590 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008591 }
8592
8593 # add namespaces and classes
8594 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8595 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008596 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008597 }
8598 # some GCC versions don't include class methods to the TU dump by default
8599 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008600 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008601 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8602 {
8603 next if($C_Structure{$CName});
8604 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008605 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008606 if(not $Force and $GCC_44
8607 and $OSgroup eq "linux")
8608 { # optimization for linux with GCC >= 4.4
8609 # disable this code by -force option
8610 if(index($CName, "::")!=-1)
8611 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008612 next;
8613 }
8614 }
8615 else
8616 {
8617 if($CName=~/\A(.+)::[^:]+\Z/
8618 and $TUnit_Classes{$Version}{$1})
8619 { # classes inside other classes
8620 next;
8621 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008622 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008623 if(defined $TUnit_Funcs{$Version}{$CName})
8624 { # the same name for a function and type
8625 next;
8626 }
8627 if(defined $TUnit_Vars{$Version}{$CName})
8628 { # the same name for a variable and type
8629 next;
8630 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008631 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8632 }
8633 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008634 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008635 }
8636 }
8637 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8638 # create TU dump
8639 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008640 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008641 or $MinGWMode{$Version}==1) {
8642 $TUdump .= " -fpreprocessed";
8643 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008644 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008645 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8646 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008647 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008648 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008649 if($?)
8650 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008651 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008652 { # try to recompile
8653 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008654 if($CppMode{$Version}==1
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008655 and index($Errors, "c99_")!=-1)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008656 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008657 $CppMode{$Version}=-1;
8658 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008659 resetLogging($Version);
8660 $TMP_DIR = tempdir(CLEANUP=>1);
8661 return getDump();
8662 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008663 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008664 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008665 { # add auto preamble headers and try again
8666 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008667 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008668 foreach my $Num (0 .. $#Headers)
8669 {
8670 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008671 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8672 {
8673 push_U($Include_Preamble{$Version}, $Path);
8674 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008675 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008676 }
8677 resetLogging($Version);
8678 $TMP_DIR = tempdir(CLEANUP=>1);
8679 return getDump();
8680 }
8681 elsif($Cpp0xMode{$Version}!=-1
8682 and ($Errors=~/\Q-std=c++0x\E/
8683 or $Errors=~/is not a class or namespace/))
8684 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008685 if(check_gcc($GCC_PATH, "4.6"))
8686 {
8687 $Cpp0xMode{$Version}=-1;
8688 printMsg("INFO", "Enabling c++0x mode");
8689 resetLogging($Version);
8690 $TMP_DIR = tempdir(CLEANUP=>1);
8691 $CompilerOptions{$Version} .= " -std=c++0x";
8692 return getDump();
8693 }
8694 else {
8695 printMsg("WARNING", "Probably c++0x construction detected");
8696 }
8697
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008698 }
8699 elsif($MinGWMode{$Version}==1)
8700 { # disable MinGW mode and try again
8701 $MinGWMode{$Version}=-1;
8702 resetLogging($Version);
8703 $TMP_DIR = tempdir(CLEANUP=>1);
8704 return getDump();
8705 }
8706 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008707 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008708 else {
8709 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008710 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008711 printMsg("ERROR", "some errors occurred when compiling headers");
8712 printErrorLog($Version);
8713 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008714 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008715 }
8716 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008717 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008718 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008719
8720 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8721 return $TUs[0];
8722 }
8723 else
8724 {
8725 my $Msg = "can't compile header(s)";
8726 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8727 $Msg .= "\nDid you install G++?";
8728 }
8729 exitStatus("Cannot_Compile", $Msg);
8730 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008731}
8732
8733sub cmd_file($)
8734{
8735 my $Path = $_[0];
8736 return "" if(not $Path or not -e $Path);
8737 if(my $CmdPath = get_CmdPath("file")) {
8738 return `$CmdPath -b \"$Path\"`;
8739 }
8740 return "";
8741}
8742
8743sub getIncString($$)
8744{
8745 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008746 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008747 my $String = "";
8748 foreach (@{$ArrRef}) {
8749 $String .= " ".inc_opt($_, $Style);
8750 }
8751 return $String;
8752}
8753
8754sub getIncPaths(@)
8755{
8756 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008757 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008758 if($INC_PATH_AUTODETECT{$Version})
8759 { # auto-detecting dependencies
8760 my %Includes = ();
8761 foreach my $HPath (@HeaderPaths)
8762 {
8763 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8764 {
8765 if($Skip_Include_Paths{$Version}{$Dir}) {
8766 next;
8767 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008768 if($SystemRoot)
8769 {
8770 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8771 next;
8772 }
8773 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008774 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008775 }
8776 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008777 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008778 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008779 }
8780 }
8781 else
8782 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008783 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008784 }
8785 return \@IncPaths;
8786}
8787
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008788sub push_U($@)
8789{ # push unique
8790 if(my $Array = shift @_)
8791 {
8792 if(@_)
8793 {
8794 my %Exist = map {$_=>1} @{$Array};
8795 foreach my $Elem (@_)
8796 {
8797 if(not defined $Exist{$Elem})
8798 {
8799 push(@{$Array}, $Elem);
8800 $Exist{$Elem} = 1;
8801 }
8802 }
8803 }
8804 }
8805}
8806
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008807sub callPreprocessor($$$)
8808{
8809 my ($Path, $Inc, $LibVersion) = @_;
8810 return "" if(not $Path or not -f $Path);
8811 my $IncludeString=$Inc;
8812 if(not $Inc) {
8813 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8814 }
8815 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008816 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008817 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008818 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008819}
8820
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008821sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008822{ # native "find" is much faster than File::Find (~6x)
8823 # also the File::Find doesn't support --maxdepth N option
8824 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008825 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008826 return () if(not $Path or not -e $Path);
8827 if($OSgroup eq "windows")
8828 {
8829 my $DirCmd = get_CmdPath("dir");
8830 if(not $DirCmd) {
8831 exitStatus("Not_Found", "can't find \"dir\" command");
8832 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008833 $Path = get_abs_path($Path);
8834 $Path = path_format($Path, $OSgroup);
8835 my $Cmd = $DirCmd." \"$Path\" /B /O";
8836 if($MaxDepth!=1) {
8837 $Cmd .= " /S";
8838 }
8839 if($Type eq "d") {
8840 $Cmd .= " /AD";
8841 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008842 elsif($Type eq "f") {
8843 $Cmd .= " /A-D";
8844 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008845 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008846 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008847 {
8848 if(not $UseRegex)
8849 { # FIXME: how to search file names in MS shell?
8850 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008851 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008852 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008853 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008854 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008855 }
8856 my @AbsPaths = ();
8857 foreach my $File (@Files)
8858 {
8859 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008860 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008861 }
8862 if($Type eq "f" and not -f $File)
8863 { # skip dirs
8864 next;
8865 }
8866 push(@AbsPaths, path_format($File, $OSgroup));
8867 }
8868 if($Type eq "d") {
8869 push(@AbsPaths, $Path);
8870 }
8871 return @AbsPaths;
8872 }
8873 else
8874 {
8875 my $FindCmd = get_CmdPath("find");
8876 if(not $FindCmd) {
8877 exitStatus("Not_Found", "can't find a \"find\" command");
8878 }
8879 $Path = get_abs_path($Path);
8880 if(-d $Path and -l $Path
8881 and $Path!~/\/\Z/)
8882 { # for directories that are symlinks
8883 $Path.="/";
8884 }
8885 my $Cmd = $FindCmd." \"$Path\"";
8886 if($MaxDepth) {
8887 $Cmd .= " -maxdepth $MaxDepth";
8888 }
8889 if($Type) {
8890 $Cmd .= " -type $Type";
8891 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008892 if($Name and not $UseRegex)
8893 { # wildcards
8894 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008895 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008896 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008897 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008898 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8899 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008900 my @Files = split(/\n/, $Res);
8901 if($Name and $UseRegex)
8902 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008903 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008904 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008905 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008906 }
8907}
8908
8909sub unpackDump($)
8910{
8911 my $Path = $_[0];
8912 return "" if(not $Path or not -e $Path);
8913 $Path = get_abs_path($Path);
8914 $Path = path_format($Path, $OSgroup);
8915 my ($Dir, $FileName) = separate_path($Path);
8916 my $UnpackDir = $TMP_DIR."/unpack";
8917 rmtree($UnpackDir);
8918 mkpath($UnpackDir);
8919 if($FileName=~s/\Q.zip\E\Z//g)
8920 { # *.zip
8921 my $UnzipCmd = get_CmdPath("unzip");
8922 if(not $UnzipCmd) {
8923 exitStatus("Not_Found", "can't find \"unzip\" command");
8924 }
8925 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008926 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008927 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008928 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008929 }
8930 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008931 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008932 if(not @Contents) {
8933 exitStatus("Error", "can't extract \'$Path\'");
8934 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008935 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008936 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008937 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008938 { # *.tar.gz
8939 if($OSgroup eq "windows")
8940 { # -xvzf option is not implemented in tar.exe (2003)
8941 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8942 my $TarCmd = get_CmdPath("tar");
8943 if(not $TarCmd) {
8944 exitStatus("Not_Found", "can't find \"tar\" command");
8945 }
8946 my $GzipCmd = get_CmdPath("gzip");
8947 if(not $GzipCmd) {
8948 exitStatus("Not_Found", "can't find \"gzip\" command");
8949 }
8950 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008951 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008952 if($?) {
8953 exitStatus("Error", "can't extract \'$Path\'");
8954 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008955 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008956 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008957 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008958 }
8959 chdir($ORIG_DIR);
8960 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008961 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008962 if(not @Contents) {
8963 exitStatus("Error", "can't extract \'$Path\'");
8964 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008965 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008966 }
8967 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008968 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008969 my $TarCmd = get_CmdPath("tar");
8970 if(not $TarCmd) {
8971 exitStatus("Not_Found", "can't find \"tar\" command");
8972 }
8973 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008974 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008975 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008976 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008977 }
8978 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008979 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008980 if(not @Contents) {
8981 exitStatus("Error", "can't extract \'$Path\'");
8982 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008983 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008984 }
8985 }
8986}
8987
8988sub createArchive($$)
8989{
8990 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008991 if(not $To) {
8992 $To = ".";
8993 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008994 if(not $Path or not -e $Path
8995 or not -d $To) {
8996 return "";
8997 }
8998 my ($From, $Name) = separate_path($Path);
8999 if($OSgroup eq "windows")
9000 { # *.zip
9001 my $ZipCmd = get_CmdPath("zip");
9002 if(not $ZipCmd) {
9003 exitStatus("Not_Found", "can't find \"zip\"");
9004 }
9005 my $Pkg = $To."/".$Name.".zip";
9006 unlink($Pkg);
9007 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04009008 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009009 if($?)
9010 { # cannot allocate memory (or other problems with "zip")
9011 unlink($Path);
9012 exitStatus("Error", "can't pack the ABI dump: ".$!);
9013 }
9014 chdir($ORIG_DIR);
9015 unlink($Path);
9016 return $Pkg;
9017 }
9018 else
9019 { # *.tar.gz
9020 my $TarCmd = get_CmdPath("tar");
9021 if(not $TarCmd) {
9022 exitStatus("Not_Found", "can't find \"tar\"");
9023 }
9024 my $GzipCmd = get_CmdPath("gzip");
9025 if(not $GzipCmd) {
9026 exitStatus("Not_Found", "can't find \"gzip\"");
9027 }
9028 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
9029 unlink($Pkg);
9030 chdir($From);
9031 system($TarCmd, "-czf", $Pkg, $Name);
9032 if($?)
9033 { # cannot allocate memory (or other problems with "tar")
9034 unlink($Path);
9035 exitStatus("Error", "can't pack the ABI dump: ".$!);
9036 }
9037 chdir($ORIG_DIR);
9038 unlink($Path);
9039 return $To."/".$Name.".tar.gz";
9040 }
9041}
9042
9043sub is_header_file($)
9044{
9045 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
9046 return $_[0];
9047 }
9048 return 0;
9049}
9050
9051sub is_not_header($)
9052{
9053 if($_[0]=~/\.\w+\Z/
9054 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
9055 return 1;
9056 }
9057 return 0;
9058}
9059
9060sub is_header($$$)
9061{
9062 my ($Header, $UserDefined, $LibVersion) = @_;
9063 return 0 if(-d $Header);
9064 if(-f $Header) {
9065 $Header = get_abs_path($Header);
9066 }
9067 else
9068 {
9069 if(is_abs($Header))
9070 { # incorrect absolute path
9071 return 0;
9072 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009073 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009074 $Header = $HPath;
9075 }
9076 else
9077 { # can't find header
9078 return 0;
9079 }
9080 }
9081 if($Header=~/\.\w+\Z/)
9082 { # have an extension
9083 return is_header_file($Header);
9084 }
9085 else
9086 {
9087 if($UserDefined==2)
9088 { # specified on the command line
9089 if(cmd_file($Header)!~/HTML|XML/i) {
9090 return $Header;
9091 }
9092 }
9093 elsif($UserDefined)
9094 { # specified in the XML-descriptor
9095 # header file without an extension
9096 return $Header;
9097 }
9098 else
9099 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009100 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009101 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009102 { # !~/HTML|XML|shared|dynamic/i
9103 return $Header;
9104 }
9105 }
9106 }
9107 return 0;
9108}
9109
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009110sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009111{
9112 my $LibVersion = $_[0];
9113 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9114 {
9115 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009116 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009117
9118 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9119 detect_recursive_includes($RegHeader, $LibVersion);
9120 }
9121
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009122 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9123 {
9124 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009125
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009126 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009127 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9128 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009129 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009130 }
9131 }
9132 }
9133}
9134
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009135sub familiarDirs($$)
9136{
9137 my ($D1, $D2) = @_;
9138 if($D1 eq $D2) {
9139 return 1;
9140 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009141
9142 my $U1 = index($D1, "/usr/");
9143 my $U2 = index($D2, "/usr/");
9144
9145 if($U1==0 and $U2!=0) {
9146 return 0;
9147 }
9148
9149 if($U2==0 and $U1!=0) {
9150 return 0;
9151 }
9152
9153 if(index($D2, $D1."/")==0) {
9154 return 1;
9155 }
9156
9157 # /usr/include/DIR
9158 # /home/user/DIR
9159
9160 my $DL = get_depth($D1);
9161
9162 my @Dirs1 = ($D1);
9163 while($DL - get_depth($D1)<=2
9164 and get_depth($D1)>=4
9165 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9166 push(@Dirs1, $D1);
9167 }
9168
9169 my @Dirs2 = ($D2);
9170 while(get_depth($D2)>=4
9171 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9172 push(@Dirs2, $D2);
9173 }
9174
9175 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009176 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009177 foreach my $P2 (@Dirs2)
9178 {
9179
9180 if($P1 eq $P2) {
9181 return 1;
9182 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009183 }
9184 }
9185 return 0;
9186}
9187
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009188sub readHeaders($)
9189{
9190 $Version = $_[0];
9191 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9192 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009193 if($Debug)
9194 { # debug mode
9195 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009196 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009197 }
9198 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009199}
9200
9201sub prepareTypes($)
9202{
9203 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009204 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009205 { # support for old ABI dumps
9206 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009207 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009208 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009209 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9210 if($TName=~/\A(\w+)::(\w+)/) {
9211 my ($P1, $P2) = ($1, $2);
9212 if($P1 eq $P2) {
9213 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009214 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009215 else {
9216 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009218 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009219 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009220 }
9221 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009222 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009223 { # support for old ABI dumps
9224 # V < 2.5: array size == "number of elements"
9225 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009226 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009227 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009228 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009229 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009230 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009231 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009232 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009233 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009234 $Size *= $Base{"Size"};
9235 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009236 }
9237 else
9238 { # array[] is a pointer
9239 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009240 }
9241 }
9242 }
9243 }
9244 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009245 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009246 { # support for old ABI dumps
9247 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009248 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009249 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009250 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009251 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009252 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009253 my %Type = get_Type($TypeId, $LibVersion);
9254 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9255 my %Type2 = get_Type($TypeId_2, $V2);
9256 if($Type{"Size"} ne $Type2{"Size"}) {
9257 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009258 }
9259 }
9260 }
9261 }
9262}
9263
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009264sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009265{
9266 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009267
9268 if(not keys(%{$SymbolInfo{$LibVersion}}))
9269 { # check if input is valid
9270 if(not $ExtendedCheck and not $CheckObjectsOnly)
9271 {
9272 if($CheckHeadersOnly) {
9273 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9274 }
9275 else {
9276 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9277 }
9278 }
9279 }
9280
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009281 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009282 if(not checkDump(1, "2.10")
9283 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009284 { # different formats
9285 $Remangle = 1;
9286 }
9287 if($CheckHeadersOnly)
9288 { # different languages
9289 if($UserLang)
9290 { # --lang=LANG for both versions
9291 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9292 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9293 {
9294 if($UserLang eq "C++")
9295 { # remangle symbols
9296 $Remangle = 1;
9297 }
9298 elsif($UserLang eq "C")
9299 { # remove mangling
9300 $Remangle = -1;
9301 }
9302 }
9303 }
9304 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009305
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009306 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009307 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009308 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009309 { # support for old ABI dumps
9310 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9311 {
9312 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9313 {
9314 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9315 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009316 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009317 if(defined $DVal and $DVal ne "")
9318 {
9319 if($TName eq "char") {
9320 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9321 }
9322 elsif($TName eq "bool") {
9323 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9324 }
9325 }
9326 }
9327 }
9328 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009329 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009330 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009331 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9332 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009333 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009334 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9335 # + support for old ABI dumps
9336 next;
9337 }
9338 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009339 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009340 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009341 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009342 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009343
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009344 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009345 if(not checkDump(1, "2.12")
9346 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009347 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009348 if($ShortName eq "operator>>")
9349 {
9350 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9351 { # corrected mangling of operator>>
9352 $SRemangle = 1;
9353 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009354 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009355 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9356 {
9357 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9358 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9359 { # corrected mangling of const global data
9360 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9361 # and incorrectly mangled by old ACC versions
9362 $SRemangle = 1;
9363 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009364 }
9365 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009366 if(not $CheckHeadersOnly)
9367 { # support for old ABI dumps
9368 if(not checkDump(1, "2.17")
9369 or not checkDump(2, "2.17"))
9370 {
9371 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9372 {
9373 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9374 {
9375 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9376 {
9377 $MnglName = $ShortName;
9378 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9379 }
9380 }
9381 }
9382 }
9383 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009384 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009385 { # support for old ABI dumps: some symbols are not mangled in old dumps
9386 # mangle both sets of symbols (old and new)
9387 # NOTE: remangling all symbols by the same mangler
9388 if($MnglName=~/\A_ZN(V|)K/)
9389 { # mangling may be incorrect on old ABI dumps
9390 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009391 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009392 }
9393 if($MnglName=~/\A_ZN(K|)V/)
9394 { # mangling may be incorrect on old ABI dumps
9395 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009396 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009397 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009398 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9399 or (not $ClassID and $CheckHeadersOnly)
9400 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9401 { # support for old ABI dumps, GCC >= 4.0
9402 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009403 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009404 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009405 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009406 $MangledNames{$LibVersion}{$MnglName} = 1;
9407 }
9408 }
9409 }
9410 elsif($Remangle==-1)
9411 { # remove mangling
9412 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009413 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009414 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009415 if(not $MnglName) {
9416 next;
9417 }
9418 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9419 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009420 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9421
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009422 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009423 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009424 { # support for old dumps
9425 # add "Volatile" attribute
9426 if($MnglName=~/_Z(K|)V/) {
9427 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9428 }
9429 }
9430 # symbol and its symlink have same signatures
9431 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009432 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009433 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009434
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009435 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9436 {
9437 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9438 if($SymVer{$LibVersion}{$Alias}) {
9439 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9440 }
9441 }
9442
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009443 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009444 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009445 }
9446 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9447 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9448 }
9449 if($ExtendedCheck)
9450 { # --ext option
9451 addExtension($LibVersion);
9452 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009453
9454 # clean memory
9455 delete($SymbolInfo{$LibVersion});
9456
9457 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009458 { # detect allocable classes with public exported constructors
9459 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009460 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009461 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009462 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009463 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009464 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9465 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009466 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009467 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009468 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009469 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009470 $AllocableClass{$LibVersion}{$ClassName} = 1;
9471 }
9472 }
9473 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009474 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009475 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009476 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009477 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009478 if($CheckHeadersOnly)
9479 {
9480 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9481 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9482 { # all symbols except non-virtual inline
9483 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9484 }
9485 }
9486 else {
9487 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009488 }
9489 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009490 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009491 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009492 }
9493 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009494 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009495 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009496 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009497 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009498 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009499 if(defined $Base{"Type"}
9500 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009501 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009502 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009503 if($Name=~/<([^<>\s]+)>/)
9504 {
9505 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9506 $ReturnedClass{$LibVersion}{$Tid} = 1;
9507 }
9508 }
9509 else {
9510 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9511 }
9512 }
9513 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009514 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009515 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009516 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009517 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009518 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009519 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009520 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009521 if($Base{"Type"}=~/Struct|Class/)
9522 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009523 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009524 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9525 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009526 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009527 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009528 }
9529 }
9530 }
9531 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009532
9533 # mapping {short name => symbols}
9534 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009535 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009536 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009537 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009538 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009539 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009540 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009541 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009542 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9543 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009544 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009545 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009546 }
9547 }
9548 }
9549 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009550
9551 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009552 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009553 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009554 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009555 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009556 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9557 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009558 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009559 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009560 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009561 $ClassNames{$LibVersion}{$TName} = 1;
9562 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009563 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009564 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9565 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009566 }
9567 }
9568 }
9569 }
9570 }
9571}
9572
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009573sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009574{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009575 my ($Tid, $LibVersion) = @_;
9576 if(not $Tid) {
9577 return $Tid;
9578 }
9579
9580 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9581 {
9582 if($TName_Tid{$LibVersion}{$Name}) {
9583 return $TName_Tid{$LibVersion}{$Name};
9584 }
9585 }
9586
9587 return $Tid;
9588}
9589
9590sub register_SymbolUsage($$$)
9591{
9592 my ($InfoId, $UsedType, $LibVersion) = @_;
9593
9594 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9595 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9596 {
9597 register_TypeUsage($RTid, $UsedType, $LibVersion);
9598 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9599 }
9600 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9601 {
9602 register_TypeUsage($FCid, $UsedType, $LibVersion);
9603 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9604
9605 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9606 { # register "this" pointer
9607 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9608 }
9609 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9610 { # register "this" pointer (const method)
9611 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9612 }
9613 }
9614 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9615 {
9616 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9617 {
9618 register_TypeUsage($PTid, $UsedType, $LibVersion);
9619 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9620 }
9621 }
9622 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9623 {
9624 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9625 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9626 register_TypeUsage($TTid, $UsedType, $LibVersion);
9627 }
9628 }
9629}
9630
9631sub register_TypeUsage($$$)
9632{
9633 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009634 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009635 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009636 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009637 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009638 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009639 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009640 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009641
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009642 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009643 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009644 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009645 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009646 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009647 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9648 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9649 }
9650 }
9651
9652 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9653 {
9654 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009655 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009656 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009657 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9658 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009659 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009660 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9661 {
9662 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9663 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009664 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009665 }
9666 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009667 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009668 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009669 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009670 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9671 {
9672 register_TypeUsage($MTid, $UsedType, $LibVersion);
9673 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009674 }
9675 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009676 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009677 or $TInfo{"Type"} eq "MethodPtr"
9678 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009679 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009680 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009681 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009682 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009683 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009684 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009685 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9686 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009687 }
9688 }
9689 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009690 if($TInfo{"Type"} eq "FieldPtr")
9691 {
9692 if(my $RTid = $TInfo{"Return"}) {
9693 register_TypeUsage($RTid, $UsedType, $LibVersion);
9694 }
9695 if(my $CTid = $TInfo{"Class"}) {
9696 register_TypeUsage($CTid, $UsedType, $LibVersion);
9697 }
9698 }
9699 if($TInfo{"Type"} eq "MethodPtr")
9700 {
9701 if(my $CTid = $TInfo{"Class"}) {
9702 register_TypeUsage($CTid, $UsedType, $LibVersion);
9703 }
9704 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009705 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009706 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009707 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009708 $UsedType->{$TypeId} = 1;
9709 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9710 {
9711 register_TypeUsage($BTid, $UsedType, $LibVersion);
9712 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9713 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009714 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009715 else
9716 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9717 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009718 }
9719 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009720}
9721
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009722sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009723{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009724 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9725
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009726 if($Level eq "Dump")
9727 {
9728 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9729 { # TODO: check if this symbol is from
9730 # base classes of other target symbols
9731 return 1;
9732 }
9733 }
9734
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009735 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9736 { # stdc++ interfaces
9737 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009738 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009739
9740 my $Target = 0;
9741 if(my $Header = $SInfo->{"Header"}) {
9742 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9743 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009744 if($ExtendedCheck)
9745 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009746 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009747 $Target = 1;
9748 }
9749 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009750 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009751 {
9752 if($Target)
9753 {
9754 if($Level eq "Dump")
9755 { # dumped
9756 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009757 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009758 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009759 return 1;
9760 }
9761 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009762 else {
9763 return 1;
9764 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009765 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009766 elsif($Level eq "Source")
9767 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009768 return 1;
9769 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009770 elsif($Level eq "Binary")
9771 { # checked
9772 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9773 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9774 return 1;
9775 }
9776 }
9777 }
9778 }
9779 else
9780 { # library is available
9781 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9782 { # exported symbols
9783 return 1;
9784 }
9785 if($Level eq "Dump")
9786 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009787 if($BinaryOnly)
9788 {
9789 if($SInfo->{"Data"})
9790 {
9791 if($Target) {
9792 return 1;
9793 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009794 }
9795 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009796 else
9797 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009798 if($Target) {
9799 return 1;
9800 }
9801 }
9802 }
9803 elsif($Level eq "Source")
9804 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009805 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
9806 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009807 { # skip LOCAL symbols
9808 if($Target) {
9809 return 1;
9810 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009811 }
9812 }
9813 elsif($Level eq "Binary")
9814 { # checked
9815 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9816 {
9817 if($Target) {
9818 return 1;
9819 }
9820 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009821 }
9822 }
9823 return 0;
9824}
9825
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009826sub cleanDump($)
9827{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009828 my $LibVersion = $_[0];
9829 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9830 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009831 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9832 {
9833 delete($SymbolInfo{$LibVersion}{$InfoId});
9834 next;
9835 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009836 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009837 if(not $MnglName)
9838 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009839 delete($SymbolInfo{$LibVersion}{$InfoId});
9840 next;
9841 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009842 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009843 if(not $ShortName)
9844 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009845 delete($SymbolInfo{$LibVersion}{$InfoId});
9846 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009847 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009848 if($MnglName eq $ShortName)
9849 { # remove duplicate data
9850 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009851 }
9852 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9853 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9854 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009855 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9856 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9857 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009858 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009859 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009860 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009861 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009862 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9863 {
9864 delete($TypeInfo{$LibVersion}{$Tid});
9865 next;
9866 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009867 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009868 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009869 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009870 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9871 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9872 }
9873 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009874 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9875 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9876 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009877 }
9878}
9879
9880sub selectType($$)
9881{
9882 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009883
9884 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9885 {
9886 if(defined $TypeInfo{$LibVersion}{$Dupl})
9887 {
9888 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9889 { # duplicate
9890 return 0;
9891 }
9892 }
9893 }
9894
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009895 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9896 {
9897 if(not isBuiltIn($THeader))
9898 {
9899 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009900 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009901 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9902 {
9903 if(is_target_header($THeader, $LibVersion))
9904 { # from target headers
9905 if(not selfTypedef($Tid, $LibVersion)) {
9906 return 1;
9907 }
9908 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009909 }
9910 }
9911 }
9912 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009913 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009914}
9915
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009916sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009917{ # remove unused data types from the ABI dump
9918 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009919
9920 my %UsedType = ();
9921
9922 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009923 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009924 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009925 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009926 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009927 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009928 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009929 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009930 next;
9931 }
9932
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009933 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009934 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009935 if(selectType($Tid, $LibVersion))
9936 {
9937 my %Tree = ();
9938 register_TypeUsage($Tid, \%Tree, $LibVersion);
9939
9940 my $Tmpl = 0;
9941 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9942 {
9943 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9944 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9945 {
9946 $Tmpl = 1;
9947 last;
9948 }
9949 }
9950 if(not $Tmpl)
9951 {
9952 foreach (keys(%Tree)) {
9953 $UsedType{$_} = 1;
9954 }
9955 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009956 }
9957 }
9958 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009959
9960 my %Delete = ();
9961
9962 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009963 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009964 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009965 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009966 next;
9967 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009968
9969 if($Kind eq "Extra")
9970 {
9971 my %Tree = ();
9972 register_TypeUsage($Tid, \%Tree, $LibVersion);
9973
9974 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9975 {
9976 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9977 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9978 {
9979 $Delete{$Tid} = 1;
9980 last;
9981 }
9982 }
9983 }
9984 else
9985 {
9986 # remove type
9987 delete($TypeInfo{$LibVersion}{$Tid});
9988 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009989 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009990
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009991 if($Kind eq "Extra")
9992 { # remove duplicates
9993 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9994 {
9995 if($UsedType{$Tid})
9996 { # All & Extended
9997 next;
9998 }
9999
10000 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10001
10002 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
10003 delete($TypeInfo{$LibVersion}{$Tid});
10004 }
10005 }
10006 }
10007
10008 foreach my $Tid (keys(%Delete))
10009 {
10010 delete($TypeInfo{$LibVersion}{$Tid});
10011 }
10012}
10013
10014sub check_Completeness($$)
10015{
10016 my ($Info, $LibVersion) = @_;
10017
10018 # data types
10019 if(defined $Info->{"Memb"})
10020 {
10021 foreach my $Pos (keys(%{$Info->{"Memb"}}))
10022 {
10023 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
10024 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
10025 }
10026 }
10027 }
10028 if(defined $Info->{"Base"})
10029 {
10030 foreach my $Bid (keys(%{$Info->{"Base"}})) {
10031 check_TypeInfo($Bid, $LibVersion);
10032 }
10033 }
10034 if(defined $Info->{"BaseType"}) {
10035 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
10036 }
10037 if(defined $Info->{"TParam"})
10038 {
10039 foreach my $Pos (keys(%{$Info->{"TParam"}}))
10040 {
10041 my $TName = $Info->{"TParam"}{$Pos}{"name"};
10042 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
10043 next;
10044 }
10045 if($TName eq "_BoolType") {
10046 next;
10047 }
10048 if($TName=~/\Asizeof\(/) {
10049 next;
10050 }
10051 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10052 check_TypeInfo($Tid, $LibVersion);
10053 }
10054 else
10055 {
10056 if(defined $Debug) {
10057 printMsg("WARNING", "missed type $TName");
10058 }
10059 }
10060 }
10061 }
10062
10063 # symbols
10064 if(defined $Info->{"Param"})
10065 {
10066 foreach my $Pos (keys(%{$Info->{"Param"}}))
10067 {
10068 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10069 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10070 }
10071 }
10072 }
10073 if(defined $Info->{"Return"}) {
10074 check_TypeInfo($Info->{"Return"}, $LibVersion);
10075 }
10076 if(defined $Info->{"Class"}) {
10077 check_TypeInfo($Info->{"Class"}, $LibVersion);
10078 }
10079}
10080
10081sub check_TypeInfo($$)
10082{
10083 my ($Tid, $LibVersion) = @_;
10084
10085 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10086 return;
10087 }
10088 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10089
10090 if(defined $TypeInfo{$LibVersion}{$Tid})
10091 {
10092 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10093 printMsg("ERROR", "missed type name ($Tid)");
10094 }
10095 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10096 }
10097 else {
10098 printMsg("ERROR", "missed type id $Tid");
10099 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010100}
10101
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010102sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010103{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010104 my ($TypeId, $LibVersion) = @_;
10105 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010106 if($Type{"Type"} eq "Typedef")
10107 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010108 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010109 if($Base{"Type"}=~/Class|Struct/)
10110 {
10111 if($Type{"Name"} eq $Base{"Name"}) {
10112 return 1;
10113 }
10114 elsif($Type{"Name"}=~/::(\w+)\Z/)
10115 {
10116 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10117 { # QPointer<QWidget>::QPointer
10118 return 1;
10119 }
10120 }
10121 }
10122 }
10123 return 0;
10124}
10125
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010126sub addExtension($)
10127{
10128 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010129 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010130 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010131 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010132 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010133 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10134 $TName=~s/\A(struct|union|class|enum) //;
10135 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010136
10137 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10138 "Header" => "extended.h",
10139 "ShortName" => $Symbol,
10140 "MnglName" => $Symbol,
10141 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10142 );
10143
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010144 $ExtendedSymbols{$Symbol} = 1;
10145 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10146 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010147 }
10148 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010149 $ExtendedSymbols{"external_func_0"} = 1;
10150 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10151 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010152}
10153
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010154sub findMethod($$$)
10155{
10156 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010157 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010158 {
10159 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10160 return $VirtMethodInClass;
10161 }
10162 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10163 return $VirtMethodInBaseClasses;
10164 }
10165 }
10166 return "";
10167}
10168
10169sub findMethod_Class($$$)
10170{
10171 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010172 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010173 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10174 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10175 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10176 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10177 { # search for interface with the same parameters suffix (overridden)
10178 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10179 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010180 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10181 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010182 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10183 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010184 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10185 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10186 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10187 return $Candidate;
10188 }
10189 }
10190 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010191 else
10192 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010193 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10194 return $Candidate;
10195 }
10196 }
10197 }
10198 }
10199 return "";
10200}
10201
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010202sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010203{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010204 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010205 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010206 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010207 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10208 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010209 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010210 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010211 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010212 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10213 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010214 { # pure virtual D2-destructors are marked as "virt" in the dump
10215 # virtual D2-destructors are NOT marked as "virt" in the dump
10216 # both destructors are not presented in the v-table
10217 next;
10218 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010219 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010220 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010222 }
10223}
10224
10225sub registerOverriding($)
10226{
10227 my $LibVersion = $_[0];
10228 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010229 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010230 foreach my $ClassName (@Classes)
10231 {
10232 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10233 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010234 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10235 { # pure virtuals
10236 next;
10237 }
10238 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10239 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010240 {
10241 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10242 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10243 { # both overridden virtual methods
10244 # and implemented pure virtual methods
10245 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10246 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10247 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010249 }
10250 }
10251 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10252 delete($VirtualTable{$LibVersion}{$ClassName});
10253 }
10254 }
10255}
10256
10257sub setVirtFuncPositions($)
10258{
10259 my $LibVersion = $_[0];
10260 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10261 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010262 my ($Num, $Rel) = (1, 0);
10263
10264 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010265 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010266 if($UsedDump{$LibVersion}{"DWARF"}) {
10267 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10268 }
10269 else {
10270 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10271 }
10272 foreach my $VirtFunc (@Funcs)
10273 {
10274 if($UsedDump{$LibVersion}{"DWARF"}) {
10275 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10276 }
10277 else {
10278 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10279 }
10280
10281 # set relative positions
10282 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10283 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10284 { # relative position excluding added and removed virtual functions
10285 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10286 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10287 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10288 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010289 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010291 }
10292 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010293 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010294 {
10295 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010296 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010297 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010298 }
10299 }
10300}
10301
10302sub get_sub_classes($$$)
10303{
10304 my ($ClassId, $LibVersion, $Recursive) = @_;
10305 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10306 my @Subs = ();
10307 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10308 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010309 if($Recursive)
10310 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010311 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10312 push(@Subs, $SubSubId);
10313 }
10314 }
10315 push(@Subs, $SubId);
10316 }
10317 return @Subs;
10318}
10319
10320sub get_base_classes($$$)
10321{
10322 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010323 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010324 return () if(not defined $ClassType{"Base"});
10325 my @Bases = ();
10326 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10327 keys(%{$ClassType{"Base"}}))
10328 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010329 if($Recursive)
10330 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010331 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10332 push(@Bases, $SubBaseId);
10333 }
10334 }
10335 push(@Bases, $BaseId);
10336 }
10337 return @Bases;
10338}
10339
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010340sub getVTable_Model($$)
10341{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010342 my ($ClassId, $LibVersion) = @_;
10343 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10344 my @Elements = ();
10345 foreach my $BaseId (@Bases, $ClassId)
10346 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010347 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010348 {
10349 if(defined $VirtualTable{$LibVersion}{$BName})
10350 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010351 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10352 if($UsedDump{$LibVersion}{"DWARF"}) {
10353 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10354 }
10355 else {
10356 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10357 }
10358 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010359 push(@Elements, $VFunc);
10360 }
10361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010362 }
10363 }
10364 return @Elements;
10365}
10366
10367sub getVShift($$)
10368{
10369 my ($ClassId, $LibVersion) = @_;
10370 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10371 my $VShift = 0;
10372 foreach my $BaseId (@Bases)
10373 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010374 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010375 {
10376 if(defined $VirtualTable{$LibVersion}{$BName}) {
10377 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10378 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010379 }
10380 }
10381 return $VShift;
10382}
10383
10384sub getShift($$)
10385{
10386 my ($ClassId, $LibVersion) = @_;
10387 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10388 my $Shift = 0;
10389 foreach my $BaseId (@Bases)
10390 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010391 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010392 {
10393 if($Size!=1)
10394 { # not empty base class
10395 $Shift+=$Size;
10396 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010397 }
10398 }
10399 return $Shift;
10400}
10401
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010402sub getVTable_Size($$)
10403{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010404 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010405 my $Size = 0;
10406 # three approaches
10407 if(not $Size)
10408 { # real size
10409 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10410 $Size = keys(%VTable);
10411 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010412 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010413 if(not $Size)
10414 { # shared library symbol size
10415 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10416 $Size /= $WORD_SIZE{$LibVersion};
10417 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010418 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010419 if(not $Size)
10420 { # model size
10421 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10422 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10423 }
10424 }
10425 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010426}
10427
10428sub isCopyingClass($$)
10429{
10430 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010431 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010432}
10433
10434sub isLeafClass($$)
10435{
10436 my ($ClassId, $LibVersion) = @_;
10437 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10438}
10439
10440sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010441{ # check structured type for public fields
10442 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010443}
10444
10445sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010446{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010447 my ($TypePtr, $Skip, $Start, $End) = @_;
10448 return 0 if(not $TypePtr);
10449 if($End==-1) {
10450 $End = keys(%{$TypePtr->{"Memb"}})-1;
10451 }
10452 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10453 {
10454 if($Skip and $Skip->{$MemPos})
10455 { # skip removed/added fields
10456 next;
10457 }
10458 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10459 {
10460 if(isPublic($TypePtr, $MemPos)) {
10461 return ($MemPos+1);
10462 }
10463 }
10464 }
10465 return 0;
10466}
10467
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010468sub isReserved($)
10469{ # reserved fields == private
10470 my $MName = $_[0];
10471 if($MName=~/reserved|padding|f_spare/i) {
10472 return 1;
10473 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010474 if($MName=~/\A[_]*(spare|pad|unused)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010475 return 1;
10476 }
10477 if($MName=~/(pad\d+)/i) {
10478 return 1;
10479 }
10480 return 0;
10481}
10482
10483sub isPublic($$)
10484{
10485 my ($TypePtr, $FieldPos) = @_;
10486 return 0 if(not $TypePtr);
10487 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10488 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10489 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10490 { # by name in C language
10491 # FIXME: add other methods to detect private members
10492 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10493 if($MName=~/priv|abidata|parent_object/i)
10494 { # C-styled private data
10495 return 0;
10496 }
10497 if(lc($MName) eq "abi")
10498 { # ABI information/reserved field
10499 return 0;
10500 }
10501 if(isReserved($MName))
10502 { # reserved fields
10503 return 0;
10504 }
10505 return 1;
10506 }
10507 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10508 { # by access in C++ language
10509 return 1;
10510 }
10511 return 0;
10512}
10513
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010514sub getVTable_Real($$)
10515{
10516 my ($ClassName, $LibVersion) = @_;
10517 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10518 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010519 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010520 if(defined $Type{"VTable"}) {
10521 return %{$Type{"VTable"}};
10522 }
10523 }
10524 return ();
10525}
10526
10527sub cmpVTables($)
10528{
10529 my $ClassName = $_[0];
10530 my $Res = cmpVTables_Real($ClassName, 1);
10531 if($Res==-1) {
10532 $Res = cmpVTables_Model($ClassName);
10533 }
10534 return $Res;
10535}
10536
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010537sub cmpVTables_Model($)
10538{
10539 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010540 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010541 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010542 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010543 return 1;
10544 }
10545 }
10546 return 0;
10547}
10548
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010549sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010550{
10551 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010552 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10553 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010554 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010555 my %VTable_Old = getVTable_Real($ClassName, 1);
10556 my %VTable_New = getVTable_Real($ClassName, 2);
10557 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010558 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010559 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010560 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010561 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010562 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10563 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010564 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010565 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010566 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010567 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010568 my $Entry1 = $VTable_Old{$Offset};
10569 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010570 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010571 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010572 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010573 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010574 $Entry1 = simpleVEntry($Entry1);
10575 $Entry2 = simpleVEntry($Entry2);
10576 if($Entry1 ne $Entry2)
10577 { # register as changed
10578 if($Entry1=~/::([^:]+)\Z/)
10579 {
10580 my $M1 = $1;
10581 if($Entry2=~/::([^:]+)\Z/)
10582 {
10583 my $M2 = $1;
10584 if($M1 eq $M2)
10585 { # overridden
10586 next;
10587 }
10588 }
10589 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010590 if(differentDumps("G"))
10591 {
10592 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10593 {
10594 # GCC 4.6.1: -0x00000000000000010
10595 # GCC 4.7.0: -16
10596 next;
10597 }
10598 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010599 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010600 }
10601 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010602 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010603}
10604
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010605sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010606{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010607 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010608 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10609 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010610 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010611 { # already registered
10612 next;
10613 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010614 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010615 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010616 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010617 foreach my $Symbol (@Affected)
10618 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010619 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010620 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010621 "Target"=>$ClassName);
10622 }
10623 }
10624 }
10625}
10626
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010627sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010628{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010629 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010630 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010631 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010632 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010633 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010634 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010635 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010636 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010637 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010638 if($TName_Tid{1}{$ClassName}
10639 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010640 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010641 if(defined $CompleteSignature{1}{$Symbol}
10642 and $CompleteSignature{1}{$Symbol}{"Virt"})
10643 { # override some method in v.1
10644 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010645 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010646 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010647 }
10648 }
10649 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010650 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010651 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010652 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010653 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010654 if($TName_Tid{2}{$ClassName}
10655 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010656 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010657 if(defined $CompleteSignature{2}{$Symbol}
10658 and $CompleteSignature{2}{$Symbol}{"Virt"})
10659 { # override some method in v.2
10660 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010661 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010662 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010663 }
10664 }
10665 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010666 if($Level eq "Binary")
10667 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010668 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010669 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10670 { # check replacements, including pure virtual methods
10671 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10672 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010673 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010674 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10675 if($AddedPos==$RemovedPos)
10676 {
10677 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10678 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10679 last; # other methods will be reported as "added" or "removed"
10680 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010681 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010682 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10683 {
10684 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10685 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010686 next;
10687 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010688 my $ProblemType = "Virtual_Replacement";
10689 my @Affected = ($RemovedVFunc);
10690 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10691 { # pure methods
10692 if(not isUsedClass($ClassId, 1, $Level))
10693 { # not a parameter of some exported method
10694 next;
10695 }
10696 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010697
10698 # affected all methods (both virtual and non-virtual ones)
10699 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10700 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010701 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010702 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010703 foreach my $AffectedInt (@Affected)
10704 {
10705 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10706 { # affected exported methods only
10707 next;
10708 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010709 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10710 next;
10711 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010712 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10713 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010714 "Target"=>get_Signature($AddedVFunc, 2),
10715 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10716 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010717 }
10718 }
10719 }
10720 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010721 if(not checkDump(1, "2.0")
10722 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010723 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010724 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010725 return;
10726 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010727 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010728 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010729 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010730 next if(not $ClassId_Old);
10731 if(not isCreatable($ClassId_Old, 1))
10732 { # skip classes without public constructors (including auto-generated)
10733 # example: class has only a private exported or private inline constructor
10734 next;
10735 }
10736 if($ClassName=~/>/)
10737 { # skip affected template instances
10738 next;
10739 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010740 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010741 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010742 if(not $ClassId_New) {
10743 next;
10744 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010745 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010746 if($Class_New{"Type"}!~/Class|Struct/)
10747 { # became typedef
10748 if($Level eq "Binary") {
10749 next;
10750 }
10751 if($Level eq "Source")
10752 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010753 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010754 if($Class_New{"Type"}!~/Class|Struct/) {
10755 next;
10756 }
10757 $ClassId_New = $Class_New{"Tid"};
10758 }
10759 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010760 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10761 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 +040010762
10763 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10764 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10765
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010766 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010767 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10768 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010769 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10770 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010771 my $Shift_Old = getShift($ClassId_Old, 1);
10772 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010773 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010774 my ($Added, $Removed) = (0, 0);
10775 my @StableBases_Old = ();
10776 foreach my $BaseId (@Bases_Old)
10777 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010778 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010779 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010780 push(@StableBases_Old, $BaseId);
10781 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010782 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010783 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010784 { # removed base
10785 # excluding namespace::SomeClass to SomeClass renaming
10786 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010787 if($Level eq "Binary")
10788 { # Binary-level
10789 if($Shift_Old ne $Shift_New)
10790 { # affected fields
10791 if(havePubFields(\%Class_Old)) {
10792 $ProblemKind .= "_And_Shift";
10793 }
10794 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10795 $ProblemKind .= "_And_Size";
10796 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010797 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010798 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10799 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010800 { # affected v-table
10801 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010802 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010803 }
10804 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010805 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010806 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10807 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010808 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10809 {
10810 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10811 if($ProblemKind=~/VTable/) {
10812 $VTableChanged_M{$SubName}=1;
10813 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010814 }
10815 }
10816 foreach my $Interface (@Affected)
10817 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010818 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10819 next;
10820 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010821 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010822 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010823 "Target"=>$BaseName,
10824 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10825 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10826 "Shift"=>abs($Shift_New-$Shift_Old) );
10827 }
10828 $Removed+=1;
10829 }
10830 }
10831 my @StableBases_New = ();
10832 foreach my $BaseId (@Bases_New)
10833 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010834 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010835 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010836 push(@StableBases_New, $BaseId);
10837 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010838 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010839 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010840 { # added base
10841 # excluding namespace::SomeClass to SomeClass renaming
10842 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010843 if($Level eq "Binary")
10844 { # Binary-level
10845 if($Shift_Old ne $Shift_New)
10846 { # affected fields
10847 if(havePubFields(\%Class_Old)) {
10848 $ProblemKind .= "_And_Shift";
10849 }
10850 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10851 $ProblemKind .= "_And_Size";
10852 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010853 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010854 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10855 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010856 { # affected v-table
10857 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010858 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010859 }
10860 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010861 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010862 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10863 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010864 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10865 {
10866 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10867 if($ProblemKind=~/VTable/) {
10868 $VTableChanged_M{$SubName}=1;
10869 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010870 }
10871 }
10872 foreach my $Interface (@Affected)
10873 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010874 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10875 next;
10876 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010877 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010878 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010879 "Target"=>$BaseName,
10880 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10881 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10882 "Shift"=>abs($Shift_New-$Shift_Old) );
10883 }
10884 $Added+=1;
10885 }
10886 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010887 if($Level eq "Binary")
10888 { # Binary-level
10889 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010890 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10891 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010892 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010893 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010894 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010895 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010896 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010897 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10898 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010899 if($NewPos!=$OldPos)
10900 { # changed position of the base class
10901 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010902 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010903 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10904 next;
10905 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010906 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10907 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010908 "Target"=>$BaseName,
10909 "Old_Value"=>$OldPos-1,
10910 "New_Value"=>$NewPos-1 );
10911 }
10912 }
10913 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10914 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10915 { # became non-virtual base
10916 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10917 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010918 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10919 next;
10920 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010921 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10922 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010923 "Target"=>$BaseName );
10924 }
10925 }
10926 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10927 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10928 { # became virtual base
10929 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10930 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010931 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10932 next;
10933 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010934 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10935 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010936 "Target"=>$BaseName );
10937 }
10938 }
10939 }
10940 }
10941 # detect size changes in base classes
10942 if($Shift_Old!=$Shift_New)
10943 { # size of allocable class
10944 foreach my $BaseId (@StableBases_Old)
10945 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010946 my %BaseType = get_Type($BaseId, 1);
10947 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010948 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010949 if($Size_Old ne $Size_New
10950 and $Size_Old and $Size_New)
10951 {
10952 my $ProblemType = "";
10953 if(isCopyingClass($BaseId, 1)) {
10954 $ProblemType = "Size_Of_Copying_Class";
10955 }
10956 elsif($AllocableClass{1}{$BaseType{"Name"}})
10957 {
10958 if($Size_New>$Size_Old)
10959 { # increased size
10960 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010961 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010962 else
10963 { # decreased size
10964 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10965 if(not havePubFields(\%Class_Old))
10966 { # affected class has no public members
10967 next;
10968 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010969 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010970 }
10971 next if(not $ProblemType);
10972 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10973 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010974 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10975 next;
10976 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010977 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10978 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010979 "Target"=>$BaseType{"Name"},
10980 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10981 "New_Size"=>$Size_New*$BYTE_SIZE );
10982 }
10983 }
10984 }
10985 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010986 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010987 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010988 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010989 { # compare virtual tables size in base classes
10990 my $VShift_Old = getVShift($ClassId_Old, 1);
10991 my $VShift_New = getVShift($ClassId_New, 2);
10992 if($VShift_Old ne $VShift_New)
10993 { # changes in the base class or changes in the list of base classes
10994 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10995 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10996 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010997 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010998 foreach my $BaseId (@AllBases_Old)
10999 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011000 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011001 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011002 { # lost base
11003 next;
11004 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011005 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
11006 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011007 if($VSize_Old!=$VSize_New)
11008 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011009 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011010 { # TODO: affected non-virtual methods?
11011 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011012 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
11013 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011014 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011015 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011016 { # skip interfaces that have not changed the absolute virtual position
11017 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011018 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011019 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
11020 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011021 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011022 $VTableChanged_M{$BaseType{"Name"}} = 1;
11023 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011024 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11025 { # the reason of the layout change: added virtual functions
11026 next if($VirtualReplacement{$VirtFunc});
11027 my $ProblemType = "Added_Virtual_Method";
11028 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11029 $ProblemType = "Added_Pure_Virtual_Method";
11030 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011031 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011032 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011033 "Target"=>get_Signature($VirtFunc, 2) );
11034 }
11035 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11036 { # the reason of the layout change: removed virtual functions
11037 next if($VirtualReplacement{$VirtFunc});
11038 my $ProblemType = "Removed_Virtual_Method";
11039 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11040 $ProblemType = "Removed_Pure_Virtual_Method";
11041 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011042 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011043 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011044 "Target"=>get_Signature($VirtFunc, 1) );
11045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011046 }
11047 }
11048 }
11049 }
11050 }
11051 }
11052 }
11053}
11054
11055sub isCreatable($$)
11056{
11057 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011058 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011059 or isCopyingClass($ClassId, $LibVersion)) {
11060 return 1;
11061 }
11062 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11063 { # Fix for incomplete data: if this class has
11064 # a base class then it should also has a constructor
11065 return 1;
11066 }
11067 if($ReturnedClass{$LibVersion}{$ClassId})
11068 { # returned by some method of this class
11069 # or any other class
11070 return 1;
11071 }
11072 return 0;
11073}
11074
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011075sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011076{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011077 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011078 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11079 { # parameter of some exported method
11080 return 1;
11081 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011082 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11083 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011084 { # method from target class
11085 return 1;
11086 }
11087 return 0;
11088}
11089
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011090sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011091{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011092 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011093 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011094 # - virtual
11095 # - pure-virtual
11096 # - non-virtual
11097 if($CompleteSignature{1}{$Interface}{"Data"})
11098 { # global data is not affected
11099 return;
11100 }
11101 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011102 if(not $Class_Id) {
11103 return;
11104 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011105 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011106 if(cmpVTables_Real($CName, 1)==0)
11107 { # no changes
11108 return;
11109 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011110 $CheckedTypes{$Level}{$CName} = 1;
11111 if($Level eq "Binary")
11112 { # Binary-level
11113 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11114 and not isUsedClass($Class_Id, 1, $Level))
11115 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011116 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011117 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011118 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011119 }
11120 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11121 {
11122 if(defined $VirtualTable{2}{$CName}{$Func}
11123 and defined $CompleteSignature{2}{$Func})
11124 {
11125 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11126 and $CompleteSignature{2}{$Func}{"PureVirt"})
11127 { # became pure virtual
11128 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11129 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011130 "Target"=>get_Signature_M($Func, 1) );
11131 $VTableChanged_M{$CName} = 1;
11132 }
11133 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11134 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11135 { # became non-pure virtual
11136 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11137 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011138 "Target"=>get_Signature_M($Func, 1) );
11139 $VTableChanged_M{$CName} = 1;
11140 }
11141 }
11142 }
11143 if($Level eq "Binary")
11144 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011145 # check virtual table structure
11146 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11147 {
11148 next if($Interface eq $AddedVFunc);
11149 next if($VirtualReplacement{$AddedVFunc});
11150 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11151 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11152 { # pure virtual methods affect all others (virtual and non-virtual)
11153 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011154 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011155 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011156 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011157 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011158 elsif(not defined $VirtualTable{1}{$CName}
11159 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011160 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011161 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011162 { # became polymorphous class, added v-table pointer
11163 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011164 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011165 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011166 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011167 }
11168 else
11169 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011170 my $VSize_Old = getVTable_Size($CName, 1);
11171 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011172 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011173 if(isCopyingClass($Class_Id, 1))
11174 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11175 my $ProblemType = "Added_Virtual_Method";
11176 if(isLeafClass($Class_Id, 1)) {
11177 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11178 }
11179 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11180 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011181 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011182 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011183 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011184 else
11185 {
11186 my $ProblemType = "Added_Virtual_Method";
11187 if(isLeafClass($Class_Id, 1)) {
11188 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11189 }
11190 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11191 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011192 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011193 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011194 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011195 }
11196 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011197 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11198 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011199 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011200 if(defined $VirtualTable{1}{$CName}
11201 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011202 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011203 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11204 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011205
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011206 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011207 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011208 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11209 foreach my $ASymbol (@Affected)
11210 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011211 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11212 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011213 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011214 next;
11215 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011216 }
11217 $CheckedSymbols{$Level}{$ASymbol} = 1;
11218 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11219 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011220 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011221 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011223 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011224 }
11225 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011226 else {
11227 # safe
11228 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011229 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011230 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11231 {
11232 next if($VirtualReplacement{$RemovedVFunc});
11233 if($RemovedVFunc eq $Interface
11234 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11235 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011236 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011237 next;
11238 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011239 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011240 { # became non-polymorphous class, removed v-table pointer
11241 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11242 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011243 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011244 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011245 }
11246 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11247 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11248 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011249 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011250 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011251 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11252 next;
11253 }
11254 my $VPos_New = -1;
11255 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011256 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011257 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11258 }
11259 else
11260 {
11261 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011262 next;
11263 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011264 }
11265 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11266 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11267 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11268 {
11269 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11270 foreach my $ASymbol (@Affected)
11271 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011272 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11273 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011274 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011275 next;
11276 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011277 }
11278 my $ProblemType = "Removed_Virtual_Method";
11279 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11280 $ProblemType = "Removed_Pure_Virtual_Method";
11281 }
11282 $CheckedSymbols{$Level}{$ASymbol} = 1;
11283 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11284 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011285 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011286 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011287 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011288 }
11289 }
11290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011291 }
11292 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011293 else
11294 { # Source-level
11295 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011296 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011297 next if($Interface eq $AddedVFunc);
11298 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011299 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011300 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11301 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011302 "Target"=>get_Signature($AddedVFunc, 2) );
11303 }
11304 }
11305 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11306 {
11307 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11308 {
11309 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11310 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011311 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011312 }
11313 }
11314 }
11315}
11316
11317sub find_MemberPair_Pos_byName($$)
11318{
11319 my ($Member_Name, $Pair_Type) = @_;
11320 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11321 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11322 {
11323 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11324 {
11325 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11326 $Name=~s/\A[_]+|[_]+\Z//g;
11327 if($Name eq $Member_Name) {
11328 return $MemberPair_Pos;
11329 }
11330 }
11331 }
11332 return "lost";
11333}
11334
11335sub find_MemberPair_Pos_byVal($$)
11336{
11337 my ($Member_Value, $Pair_Type) = @_;
11338 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11339 {
11340 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11341 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11342 return $MemberPair_Pos;
11343 }
11344 }
11345 return "lost";
11346}
11347
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011348my %Severity_Val=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011349 "High"=>3,
11350 "Medium"=>2,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011351 "Low"=>1,
11352 "Safe"=>-1
11353);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011354
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011355sub cmpSeverities($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011356{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011357 my ($S1, $S2) = @_;
11358 if(not $S1) {
11359 return 0;
11360 }
11361 elsif(not $S2) {
11362 return 1;
11363 }
11364 return ($Severity_Val{$S1}>$Severity_Val{$S2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011365}
11366
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011367sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011368{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011369 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011370 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011371 if( $_->{"T1"} eq $_[0]
11372 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011373 {
11374 return 1;
11375 }
11376 }
11377 return 0;
11378}
11379
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011380sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011381{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011382 my %IDs = (
11383 "T1" => $_[0],
11384 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011385 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011386 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011387}
11388
11389sub isRenamed($$$$$)
11390{
11391 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11392 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11393 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011394 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011395 if(not defined $Type2->{"Memb"}{$MemPos}) {
11396 return "";
11397 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011398 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011399 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011400
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011401 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11402 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011403 if($MemberPair_Pos_Rev eq "lost")
11404 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011405 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11406 { # base type match
11407 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011408 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011409 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11410 { # exact type match
11411 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011412 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011413 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11414 { # size match
11415 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011416 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011417 if(isReserved($Pair_Name))
11418 { # reserved fields
11419 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011420 }
11421 }
11422 return "";
11423}
11424
11425sub isLastElem($$)
11426{
11427 my ($Pos, $TypeRef) = @_;
11428 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11429 if($Name=~/last|count|max|total/i)
11430 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11431 return 1;
11432 }
11433 elsif($Name=~/END|NLIMITS\Z/)
11434 { # __RLIMIT_NLIMITS
11435 return 1;
11436 }
11437 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11438 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11439 { # NImageFormats, NColorRoles
11440 return 1;
11441 }
11442 return 0;
11443}
11444
11445sub nonComparable($$)
11446{
11447 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011448
11449 my $N1 = $T1->{"Name"};
11450 my $N2 = $T2->{"Name"};
11451
11452 $N1=~s/\A(struct|union|enum) //;
11453 $N2=~s/\A(struct|union|enum) //;
11454
11455 if($N1 ne $N2
11456 and not isAnon($N1)
11457 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011458 { # different names
11459 if($T1->{"Type"} ne "Pointer"
11460 or $T2->{"Type"} ne "Pointer")
11461 { # compare base types
11462 return 1;
11463 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011464 if($N1!~/\Avoid\s*\*/
11465 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011466 {
11467 return 1;
11468 }
11469 }
11470 elsif($T1->{"Type"} ne $T2->{"Type"})
11471 { # different types
11472 if($T1->{"Type"} eq "Class"
11473 and $T2->{"Type"} eq "Struct")
11474 { # "class" to "struct"
11475 return 0;
11476 }
11477 elsif($T2->{"Type"} eq "Class"
11478 and $T1->{"Type"} eq "Struct")
11479 { # "struct" to "class"
11480 return 0;
11481 }
11482 else
11483 { # "class" to "enum"
11484 # "union" to "class"
11485 # ...
11486 return 1;
11487 }
11488 }
11489 return 0;
11490}
11491
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011492sub isOpaque($)
11493{
11494 my $T = $_[0];
11495 if(not defined $T->{"Memb"})
11496 {
11497 return 1;
11498 }
11499 return 0;
11500}
11501
11502sub removeVPtr($)
11503{ # support for old ABI dumps
11504 my $TPtr = $_[0];
11505 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11506 if($#Pos>=1)
11507 {
11508 foreach my $Pos (0 .. $#Pos-1)
11509 {
11510 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11511 }
11512 delete($TPtr->{"Memb"}{$#Pos});
11513 }
11514}
11515
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011516sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011517{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011518 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011519 return {} if(not $Type1_Id or not $Type2_Id);
11520
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011521 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011522 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011523 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011524 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011525
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011526 my %Type1 = get_Type($Type1_Id, 1);
11527 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011528 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011529 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011530 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011531
11532 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011533 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11534 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011535
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011536 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11537
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011538 my %SubProblems = ();
11539
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011540 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11541 {
11542 if($Type1_Pure{"Type"}=~/Struct|Union/
11543 and $Type2_Pure{"Type"}=~/Struct|Union/)
11544 {
11545 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11546 {
11547 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11548 "Target"=>$Type1_Pure{"Name"},
11549 "Type_Name"=>$Type1_Pure{"Name"} );
11550
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011551 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011552 }
11553 }
11554 }
11555
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011556 if(not $Type1_Pure{"Size"}
11557 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011558 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011559 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11560 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11561 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011562 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011563 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011564 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011565 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011566 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011567 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011568 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011569 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11570 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11571 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011572
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011573 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11574 { # support for old ABI dumps
11575 # _vptr field added in 3.0
11576 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11577 {
11578 if(defined $Type2_Pure{"Memb"}
11579 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11580 {
11581 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11582 delete($Type2_Pure{"Memb"}{0});
11583 }
11584 else {
11585 removeVPtr(\%Type2_Pure);
11586 }
11587 }
11588 }
11589 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11590 {
11591 if(defined $Type1_Pure{"Memb"}
11592 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11593 {
11594 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11595 delete($Type1_Pure{"Memb"}{0});
11596 }
11597 else {
11598 removeVPtr(\%Type1_Pure);
11599 }
11600 }
11601 }
11602 }
11603
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011604 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11605 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011606
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011607 if(not $UseOldDumps and %Typedef_1 and %Typedef_2
11608 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11609 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011610 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011611 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11612 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011613 if($Base_1{"Name"} ne $Base_2{"Name"})
11614 {
11615 if(differentDumps("G")
11616 or differentDumps("V"))
11617 { # different GCC versions or different dumps
11618 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11619 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11620 # std::__va_list and __va_list
11621 $Base_1{"Name"}=~s/\A(\w+::)+//;
11622 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011623 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11624 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011625 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011626 }
11627 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11628 and $Base_1{"Name"} ne $Base_2{"Name"})
11629 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011630 if($Level eq "Binary"
11631 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011632 {
11633 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11634 "Target"=>$Typedef_1{"Name"},
11635 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011636 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11637 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11638 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011639 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11640 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011641 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011642 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011643 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11644 {
11645 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11646 "Target"=>$Typedef_1{"Name"},
11647 "Type_Name"=>$Typedef_1{"Name"},
11648 "Old_Value"=>$Base_1{"Name"},
11649 "New_Value"=>$Base_2{"Name"} );
11650 }
11651 else
11652 {
11653 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11654 "Target"=>$Typedef_1{"Name"},
11655 "Type_Name"=>$Typedef_1{"Name"},
11656 "Old_Value"=>$Base_1{"Name"},
11657 "New_Value"=>$Base_2{"Name"} );
11658 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011659 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011660 }
11661 }
11662 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11663 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011664 my $TT1 = $Type1_Pure{"Type"};
11665 my $TT2 = $Type2_Pure{"Type"};
11666
11667 if($TT1 ne $TT2
11668 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011669 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011670 my $Short1 = $Type1_Pure{"Name"};
11671 my $Short2 = $Type2_Pure{"Name"};
11672
11673 $Short1=~s/\A\Q$TT1\E //ig;
11674 $Short2=~s/\A\Q$TT2\E //ig;
11675
11676 if($Short1 eq $Short2)
11677 {
11678 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11679 "Target"=>$Type1_Pure{"Name"},
11680 "Type_Name"=>$Type1_Pure{"Name"},
11681 "Old_Value"=>lc($Type1_Pure{"Type"}),
11682 "New_Value"=>lc($Type2_Pure{"Type"}) );
11683 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011684 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011685 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011686 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011687 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011688 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11689 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11690 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11691 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011692 if($Level eq "Binary"
11693 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011694 {
11695 my $ProblemKind = "DataType_Size";
11696 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011697 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011698 {
11699 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11700 $ProblemKind = "Size_Of_Copying_Class";
11701 }
11702 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11703 {
11704 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11705 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11706 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011707 else
11708 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011709 # descreased size of allocable class
11710 # it has no special effects
11711 }
11712 }
11713 }
11714 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11715 "Target"=>$Type1_Pure{"Name"},
11716 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011717 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011718 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011719 }
11720 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011721 if(defined $Type1_Pure{"BaseType"}
11722 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011723 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011724 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11725 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011726 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011727 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11728 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011729 }
11730 }
11731 }
11732 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11733 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11734 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11735 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11736 { # detect removed and renamed fields
11737 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11738 next if(not $Member_Name);
11739 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);
11740 if($MemberPair_Pos eq "lost")
11741 {
11742 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11743 {
11744 if(isUnnamed($Member_Name))
11745 { # support for old-version dumps
11746 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011747 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011748 next;
11749 }
11750 }
11751 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11752 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011753 $RenamedField{$Member_Pos} = $RenamedTo;
11754 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011755 }
11756 else
11757 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011758 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011759 }
11760 }
11761 elsif($Type1_Pure{"Type"} eq "Enum")
11762 {
11763 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11764 next if($Member_Value1 eq "");
11765 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11766 if($MemberPair_Pos ne "lost")
11767 { # renamed
11768 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11769 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11770 if($MemberPair_Pos_Rev eq "lost")
11771 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011772 $RenamedField{$Member_Pos} = $RenamedTo;
11773 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011774 }
11775 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011776 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011777 }
11778 }
11779 else
11780 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011781 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011782 }
11783 }
11784 }
11785 else
11786 { # related
11787 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11788 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11789 }
11790 }
11791 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11792 { # detect added fields
11793 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11794 next if(not $Member_Name);
11795 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);
11796 if($MemberPair_Pos eq "lost")
11797 {
11798 if(isUnnamed($Member_Name))
11799 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011800 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011801 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011802 next;
11803 }
11804 }
11805 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11806 {
11807 if(not $RenamedField_Rev{$Member_Pos})
11808 { # added
11809 $AddedField{$Member_Pos}=1;
11810 }
11811 }
11812 }
11813 }
11814 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11815 { # detect moved fields
11816 my (%RelPos, %RelPosName, %AbsPos) = ();
11817 my $Pos = 0;
11818 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11819 { # relative positions in 1st version
11820 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11821 next if(not $Member_Name);
11822 if(not $RemovedField{$Member_Pos})
11823 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011824 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011825 $RelPosName{1}{$Pos} = $Member_Name;
11826 $AbsPos{1}{$Pos++} = $Member_Pos;
11827 }
11828 }
11829 $Pos = 0;
11830 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11831 { # relative positions in 2nd version
11832 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11833 next if(not $Member_Name);
11834 if(not $AddedField{$Member_Pos})
11835 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011836 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011837 $RelPosName{2}{$Pos} = $Member_Name;
11838 $AbsPos{2}{$Pos++} = $Member_Pos;
11839 }
11840 }
11841 foreach my $Member_Name (keys(%{$RelPos{1}}))
11842 {
11843 my $RPos1 = $RelPos{1}{$Member_Name};
11844 my $AbsPos1 = $NameToPosA{$Member_Name};
11845 my $Member_Name2 = $Member_Name;
11846 if(my $RenamedTo = $RenamedField{$AbsPos1})
11847 { # renamed
11848 $Member_Name2 = $RenamedTo;
11849 }
11850 my $RPos2 = $RelPos{2}{$Member_Name2};
11851 if($RPos2 ne "" and $RPos1 ne $RPos2)
11852 { # different relative positions
11853 my $AbsPos2 = $NameToPosB{$Member_Name2};
11854 if($AbsPos1 ne $AbsPos2)
11855 { # different absolute positions
11856 my $ProblemType = "Moved_Field";
11857 if(not isPublic(\%Type1_Pure, $AbsPos1))
11858 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011859 if($Level eq "Source") {
11860 next;
11861 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011862 $ProblemType = "Moved_Private_Field";
11863 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011864 if($Level eq "Binary"
11865 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011866 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011867 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011868 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011869 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011870 if($MemSize1 ne $MemSize2) {
11871 $ProblemType .= "_And_Size";
11872 }
11873 }
11874 if($ProblemType eq "Moved_Private_Field") {
11875 next;
11876 }
11877 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11878 "Target"=>$Member_Name,
11879 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011880 "Old_Value"=>$RPos1,
11881 "New_Value"=>$RPos2 );
11882 }
11883 }
11884 }
11885 }
11886 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011887 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011888 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11889 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011890 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011891 if(my $RenamedTo = $RenamedField{$Member_Pos})
11892 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011893 if(defined $Constants{2}{$Member_Name})
11894 {
11895 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11896 { # define OLD NEW
11897 next; # Safe
11898 }
11899 }
11900
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011901 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11902 {
11903 if(isPublic(\%Type1_Pure, $Member_Pos))
11904 {
11905 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11906 "Target"=>$Member_Name,
11907 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011908 "Old_Value"=>$Member_Name,
11909 "New_Value"=>$RenamedTo );
11910 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011911 elsif(isReserved($Member_Name))
11912 {
11913 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11914 "Target"=>$Member_Name,
11915 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011916 "Old_Value"=>$Member_Name,
11917 "New_Value"=>$RenamedTo );
11918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011919 }
11920 elsif($Type1_Pure{"Type"} eq "Enum")
11921 {
11922 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11923 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11924 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011925 "Old_Value"=>$Member_Name,
11926 "New_Value"=>$RenamedTo );
11927 }
11928 }
11929 elsif($RemovedField{$Member_Pos})
11930 { # removed
11931 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11932 {
11933 my $ProblemType = "Removed_Field";
11934 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011935 or isUnnamed($Member_Name))
11936 {
11937 if($Level eq "Source") {
11938 next;
11939 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011940 $ProblemType = "Removed_Private_Field";
11941 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011942 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011943 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011944 {
11945 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11946 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011947 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 +040011948 { # changed offset
11949 $ProblemType .= "_And_Layout";
11950 }
11951 }
11952 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11953 { # affected size
11954 $ProblemType .= "_And_Size";
11955 }
11956 }
11957 if($ProblemType eq "Removed_Private_Field") {
11958 next;
11959 }
11960 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11961 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011962 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011963 }
11964 elsif($Type2_Pure{"Type"} eq "Union")
11965 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011966 if($Level eq "Binary"
11967 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011968 {
11969 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11970 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011971 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011972 }
11973 else
11974 {
11975 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11976 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011977 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011978 }
11979 }
11980 elsif($Type1_Pure{"Type"} eq "Enum")
11981 {
11982 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11983 "Target"=>$Member_Name,
11984 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011985 "Old_Value"=>$Member_Name );
11986 }
11987 }
11988 else
11989 { # changed
11990 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11991 if($Type1_Pure{"Type"} eq "Enum")
11992 {
11993 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11994 next if($Member_Value1 eq "");
11995 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11996 next if($Member_Value2 eq "");
11997 if($Member_Value1 ne $Member_Value2)
11998 {
11999 my $ProblemType = "Enum_Member_Value";
12000 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12001 $ProblemType = "Enum_Last_Member_Value";
12002 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012003 if($SkipConstants{1}{$Member_Name}) {
12004 $ProblemType = "Enum_Private_Member_Value";
12005 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012006 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12007 "Target"=>$Member_Name,
12008 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012009 "Old_Value"=>$Member_Value1,
12010 "New_Value"=>$Member_Value2 );
12011 }
12012 }
12013 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12014 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012015 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12016 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12017
12018 if($Access1 ne "private"
12019 and $Access2 eq "private")
12020 {
12021 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12022 "Target"=>$Member_Name,
12023 "Type_Name"=>$Type1_Pure{"Name"});
12024 }
12025 elsif($Access1 ne "protected"
12026 and $Access1 ne "private"
12027 and $Access2 eq "protected")
12028 {
12029 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12030 "Target"=>$Member_Name,
12031 "Type_Name"=>$Type1_Pure{"Name"});
12032 }
12033
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012034 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12035 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012036 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012037 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12038 $SizeV1 = $BSize1;
12039 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012040 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012041 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12042 $SizeV2 = $BSize2;
12043 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012044 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12045 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012046 if($Level eq "Binary"
12047 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012048 {
12049 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12050 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12051 { # field size change (including anon-structures and unions)
12052 # - same types
12053 # - unnamed types
12054 # - bitfields
12055 my $ProblemType = "Field_Size";
12056 if(not isPublic(\%Type1_Pure, $Member_Pos)
12057 or isUnnamed($Member_Name))
12058 { # should not be accessed by applications, goes to "Low Severity"
12059 # example: "abidata" members in GStreamer types
12060 $ProblemType = "Private_".$ProblemType;
12061 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012062 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 +040012063 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012064 if($Type2_Pure{"Type"} ne "Union"
12065 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012066 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012067 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 +040012068 { # changed offset
12069 $ProblemType .= "_And_Layout";
12070 }
12071 }
12072 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12073 $ProblemType .= "_And_Type_Size";
12074 }
12075 }
12076 if($ProblemType eq "Private_Field_Size")
12077 { # private field size with no effect
12078 $ProblemType = "";
12079 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012080 if($ProblemType eq "Field_Size")
12081 {
12082 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12083 { # Low severity
12084 $ProblemType = "Struct_Field_Size_Increased";
12085 }
12086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012087 if($ProblemType)
12088 { # register a problem
12089 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12090 "Target"=>$Member_Name,
12091 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012092 "Old_Size"=>$SizeV1,
12093 "New_Size"=>$SizeV2);
12094 }
12095 }
12096 }
12097 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12098 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12099 { # do NOT check bitfield type changes
12100 next;
12101 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012102 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012103 {
12104 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12105 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12106 {
12107 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12108 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012109 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012110 }
12111 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12112 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12113 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012114 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012115 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012116 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012117 }
12118 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012119 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12120 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012121 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012122 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12123 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012124
12125 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012126 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012127 or $ProblemType eq "Field_Type_And_Size"
12128 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012129 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012130 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012131 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012132 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012133 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012134 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012135 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012136 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012137 }
12138 }
12139 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12140 {
12141 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012142 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012143 }
12144 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012145 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012146 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012147 }
12148 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12149 {
12150 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012151 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012152 }
12153 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012154 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012155 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012156 }
12157 }
12158 }
12159
12160 if($Level eq "Source")
12161 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012162 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012163 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012164 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12165 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012166
12167 if($ProblemType eq "Field_Type")
12168 {
12169 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012170 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012171 }
12172 }
12173 }
12174 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012175
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012176 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012177 {
12178 my $ProblemType_Init = $ProblemType;
12179 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012180 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012181 if(not isPublic(\%Type1_Pure, $Member_Pos)
12182 or isUnnamed($Member_Name)) {
12183 $ProblemType = "Private_".$ProblemType;
12184 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012185 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 +040012186 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012187 if($Type2_Pure{"Type"} ne "Union"
12188 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012189 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012190 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 +040012191 { # changed offset
12192 $ProblemType .= "_And_Layout";
12193 }
12194 }
12195 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12196 $ProblemType .= "_And_Type_Size";
12197 }
12198 }
12199 }
12200 else
12201 {
12202 if(not isPublic(\%Type1_Pure, $Member_Pos)
12203 or isUnnamed($Member_Name)) {
12204 next;
12205 }
12206 }
12207 if($ProblemType eq "Private_Field_Type_And_Size")
12208 { # private field change with no effect
12209 next;
12210 }
12211 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12212 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012213 "Type_Name"=>$Type1_Pure{"Name"});
12214
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012215 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012216 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012217 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012218 }
12219 }
12220 if(not isPublic(\%Type1_Pure, $Member_Pos))
12221 { # do NOT check internal type changes
12222 next;
12223 }
12224 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012225 { # checking member type changes
12226 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12227
12228 my %DupProblems = ();
12229
12230 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012231 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012232 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012233 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012234 if(not defined $AllAffected)
12235 {
12236 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12237 next;
12238 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012239 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012240
12241 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12242 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12243
12244 if(not defined $AllAffected)
12245 {
12246 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012247 }
12248 }
12249 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012250
12251 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012252 }
12253 }
12254 }
12255 }
12256 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12257 { # checking added members, public and private
12258 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12259 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012260 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012261 if($AddedField{$Member_Pos})
12262 { # added
12263 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12264 {
12265 my $ProblemType = "Added_Field";
12266 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012267 or isUnnamed($Member_Name))
12268 {
12269 if($Level eq "Source") {
12270 next;
12271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012272 $ProblemType = "Added_Private_Field";
12273 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012274 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012275 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012276 {
12277 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12278 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012279 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 +040012280 { # changed offset
12281 $ProblemType .= "_And_Layout";
12282 }
12283 }
12284 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12285 $ProblemType .= "_And_Size";
12286 }
12287 }
12288 if($ProblemType eq "Added_Private_Field")
12289 { # skip added private fields
12290 next;
12291 }
12292 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12293 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012294 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012295 }
12296 elsif($Type2_Pure{"Type"} eq "Union")
12297 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012298 if($Level eq "Binary"
12299 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012300 {
12301 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12302 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012303 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012304 }
12305 else
12306 {
12307 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12308 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012309 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012310 }
12311 }
12312 elsif($Type2_Pure{"Type"} eq "Enum")
12313 {
12314 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12315 next if($Member_Value eq "");
12316 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12317 "Target"=>$Member_Name,
12318 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012319 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012320 }
12321 }
12322 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012323
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012324 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012325 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012326}
12327
12328sub isUnnamed($) {
12329 return $_[0]=~/\Aunnamed\d+\Z/;
12330}
12331
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012332sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012333{
12334 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012335 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12336 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12337 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12338 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012339 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012340 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012341 }
12342 return $TypeName;
12343}
12344
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012345sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012346{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012347 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012348 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012349 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12350 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012351 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012352 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12353 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012354 return () if(not $Type{"Type"});
12355 if($Type{"Type"} ne $Type_Type)
12356 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012357 return () if(not $Type{"BaseType"});
12358 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012359 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012360 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012361 return %Type;
12362}
12363
12364my %TypeSpecAttributes = (
12365 "Const" => 1,
12366 "Volatile" => 1,
12367 "ConstVolatile" => 1,
12368 "Restrict" => 1,
12369 "Typedef" => 1
12370);
12371
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012372sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012373{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012374 my ($TypeId, $Info) = @_;
12375 if(not $TypeId or not $Info
12376 or not $Info->{$TypeId}) {
12377 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012378 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012379 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12380 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12381 }
12382 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012383 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012384 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012385 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012386 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012387 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012388 return %Type;
12389}
12390
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012391sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012392{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012393 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012394 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012395 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12396 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012397 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012398 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12399 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012400 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12401 my $PLevel = 0;
12402 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12403 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012404 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012405 return $PLevel if(not $Type{"BaseType"});
12406 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12407 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12408 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012409}
12410
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012411sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012412{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012413 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012414 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012415 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12416 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012417 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012418 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12419 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012420 return %Type if(not $Type{"BaseType"});
12421 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012422 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012423 return %Type;
12424}
12425
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012426sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012427{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012428 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012429 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012430 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12431 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012432 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012433 my $Qual = "";
12434 if($Type{"Type"} eq "Pointer") {
12435 $Qual .= "*";
12436 }
12437 elsif($Type{"Type"} eq "Ref") {
12438 $Qual .= "&";
12439 }
12440 elsif($Type{"Type"} eq "ConstVolatile") {
12441 $Qual .= "const volatile";
12442 }
12443 elsif($Type{"Type"} eq "Const"
12444 or $Type{"Type"} eq "Volatile"
12445 or $Type{"Type"} eq "Restrict") {
12446 $Qual .= lc($Type{"Type"});
12447 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012448 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012449 return $BQual.$Qual;
12450}
12451
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012452sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012453{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012454 my ($TypeId, $Info) = @_;
12455 if(not $TypeId or not $Info
12456 or not $Info->{$TypeId}) {
12457 return ();
12458 }
12459 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012460 return %Type if(not $Type{"BaseType"});
12461 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012462 {
12463 if($Info->{$BTid}) {
12464 return %{$Info->{$BTid}};
12465 }
12466 else { # something is going wrong
12467 return ();
12468 }
12469 }
12470 else {
12471 return %Type;
12472 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012473}
12474
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012475sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012476{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012477 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012478 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012479 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12480 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012481}
12482
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012483sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012484{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012485 my $Symbol = $_[0];
12486 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12487}
12488
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012489sub isInLineInst($$$) {
12490 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12491}
12492
12493sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012494{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012495 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012496 if($CheckObjectsOnly)
12497 {
12498 if($Symbol!~/\A(_Z|\?)/) {
12499 return 0;
12500 }
12501 if(my $Signature = $tr_name{$Symbol})
12502 {
12503 if(index($Signature,">")==-1) {
12504 return 0;
12505 }
12506 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
12507 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012508 if(index($ShortName,"<")!=-1
12509 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012510 return 1;
12511 }
12512 }
12513 }
12514 }
12515 else
12516 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012517 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012518 {
12519 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
12520 {
12521 if(index($ClassName,"<")!=-1) {
12522 return 1;
12523 }
12524 }
12525 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012526 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012527 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012528 if(index($ShortName,"<")!=-1
12529 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012530 return 1;
12531 }
12532 }
12533 }
12534 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012535}
12536
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012537sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012538{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012539 my ($Symbol, $SInfo, $LibVersion) = @_;
12540 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012541 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012542 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012543 { # class specialization
12544 return 1;
12545 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012546 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012547 { # method specialization
12548 return 1;
12549 }
12550 }
12551 return 0;
12552}
12553
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012554sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012555{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012556 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012557 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012558 { # non-public global data
12559 return 0;
12560 }
12561 if($CheckObjectsOnly) {
12562 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
12563 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012564 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012565 { # support for old ABI dumps in --headers-only mode
12566 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12567 {
12568 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12569 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012570 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012571 if(not $PType or $PType eq "Unknown") {
12572 return 0;
12573 }
12574 }
12575 }
12576 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012577 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012578 {
12579 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012580 if($SkipSymbols{$LibVersion}{$Symbol})
12581 { # user defined symbols to ignore
12582 return 0;
12583 }
12584 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12585 if(not $NameSpace and $ClassId)
12586 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012587 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012588 }
12589 if($NameSpace)
12590 { # user defined namespaces to ignore
12591 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12592 return 0;
12593 }
12594 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12595 { # nested namespaces
12596 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12597 return 0;
12598 }
12599 }
12600 }
12601 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
12602 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012603 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012604 { # --skip-headers or <skip_headers> (not <skip_including>)
12605 if($Skip==1) {
12606 return 0;
12607 }
12608 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012609 }
12610 if($SymbolsListPath and not $SymbolsList{$Symbol})
12611 { # user defined symbols
12612 return 0;
12613 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012614 if($SkipSymbolsListPath and $SkipSymbolsList{$Symbol})
12615 { # user defined symbols
12616 return 0;
12617 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012618 if($AppPath and not $SymbolsList_App{$Symbol})
12619 { # user defined symbols (in application)
12620 return 0;
12621 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012622 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12623 { # non-target symbols
12624 return 0;
12625 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012626 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012627 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012628 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012629 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012630 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012631 return 0;
12632 }
12633 }
12634 else
12635 {
12636 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012637 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012638 {
12639 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12640 { # inline virtual methods
12641 if($Type=~/InlineVirt/) {
12642 return 1;
12643 }
12644 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12645 if(not $Allocable)
12646 { # check bases
12647 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12648 {
12649 if(not isCopyingClass($DCId, $LibVersion))
12650 { # exists a derived class without default c-tor
12651 $Allocable=1;
12652 last;
12653 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012654 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012655 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012656 if(not $Allocable) {
12657 return 0;
12658 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012659 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012660 else
12661 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012662 return 0;
12663 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012664 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012666 }
12667 }
12668 return 1;
12669}
12670
12671sub mergeImpl()
12672{
12673 my $DiffCmd = get_CmdPath("diff");
12674 if(not $DiffCmd) {
12675 exitStatus("Not_Found", "can't find \"diff\"");
12676 }
12677 foreach my $Interface (sort keys(%{$Symbol_Library{1}}))
12678 { # implementation changes
12679 next if($CompleteSignature{1}{$Interface}{"Private"});
12680 next if(not $CompleteSignature{1}{$Interface}{"Header"} and not $CheckObjectsOnly);
12681 next if(not $Symbol_Library{2}{$Interface} and not $Symbol_Library{2}{$SymVer{2}{$Interface}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012682 if(not symbolFilter($Interface, 1, "Affected", "Binary")) {
12683 next;
12684 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012685 my $Impl1 = canonifyImpl($Interface_Impl{1}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012686 next if(not $Impl1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012687 my $Impl2 = canonifyImpl($Interface_Impl{2}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012688 next if(not $Impl2);
12689 if($Impl1 ne $Impl2)
12690 {
12691 writeFile("$TMP_DIR/impl1", $Impl1);
12692 writeFile("$TMP_DIR/impl2", $Impl2);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012693 my $Diff = `$DiffCmd -rNau \"$TMP_DIR/impl1\" \"$TMP_DIR/impl2\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012694 $Diff=~s/(---|\+\+\+).+\n//g;
12695 $Diff=~s/[ ]{3,}/ /g;
12696 $Diff=~s/\n\@\@/\n \n\@\@/g;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012697 unlink("$TMP_DIR/impl1");
12698 unlink("$TMP_DIR/impl2");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040012699 %{$CompatProblems_Impl{$Interface}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012700 "Diff" => get_CodeView($Diff) );
12701 }
12702 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012703
12704 # clean memory
12705 %Interface_Impl = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012706}
12707
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012708sub canonifyImpl($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012709{
12710 my $FuncBody= $_[0];
12711 return "" if(not $FuncBody);
12712 $FuncBody=~s/0x[a-f\d]+/0x?/g;# addr
12713 $FuncBody=~s/((\A|\n)[a-z]+[\t ]+)[a-f\d]+([^x]|\Z)/$1?$3/g;# call, jump
12714 $FuncBody=~s/# [a-f\d]+ /# ? /g;# call, jump
12715 $FuncBody=~s/%([a-z]+[a-f\d]*)/\%reg/g;# registers
12716 while($FuncBody=~s/\nnop[ \t]*(\n|\Z)/$1/g){};# empty op
12717 $FuncBody=~s/<.+?\.cpp.+?>/<name.cpp>/g;
12718 $FuncBody=~s/(\A|\n)[a-f\d]+ </$1? </g;# 5e74 <_ZN...
12719 $FuncBody=~s/\.L\d+/.L/g;
12720 $FuncBody=~s/#(-?)\d+/#$1?/g;# r3, [r3, #120]
12721 $FuncBody=~s/[\n]{2,}/\n/g;
12722 return $FuncBody;
12723}
12724
12725sub get_CodeView($)
12726{
12727 my $Code = $_[0];
12728 my $View = "";
12729 foreach my $Line (split(/\n/, $Code))
12730 {
12731 if($Line=~s/\A(\+|-)/$1 /g)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012732 { # bold line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012733 $View .= "<tr><td><b>".htmlSpecChars($Line)."</b></td></tr>\n";
12734 }
12735 else {
12736 $View .= "<tr><td>".htmlSpecChars($Line)."</td></tr>\n";
12737 }
12738 }
12739 return "<table class='code_view'>$View</table>\n";
12740}
12741
12742sub getImplementations($$)
12743{
12744 my ($LibVersion, $Path) = @_;
12745 return if(not $LibVersion or not -e $Path);
12746 if($OSgroup eq "macos")
12747 {
12748 my $OtoolCmd = get_CmdPath("otool");
12749 if(not $OtoolCmd) {
12750 exitStatus("Not_Found", "can't find \"otool\"");
12751 }
12752 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012753 foreach my $Line (split(/\n/, `$OtoolCmd -tv \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012754 {
12755 if($Line=~/\A\s*_(\w+)\s*:/i) {
12756 $CurInterface = $1;
12757 }
12758 elsif($Line=~/\A\s*[\da-z]+\s+(.+?)\Z/i) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012759 $Interface_Impl{$LibVersion}{$CurInterface} .= $1."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012760 }
12761 }
12762 }
12763 else
12764 {
12765 my $ObjdumpCmd = get_CmdPath("objdump");
12766 if(not $ObjdumpCmd) {
12767 exitStatus("Not_Found", "can't find \"objdump\"");
12768 }
12769 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012770 foreach my $Line (split(/\n/, `$ObjdumpCmd -d \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012771 {
12772 if($Line=~/\A[\da-z]+\s+<(\w+)>/i) {
12773 $CurInterface = $1;
12774 }
12775 else
12776 { # x86: 51fa:(\t)89 e5 (\t)mov %esp,%ebp
12777 # arm: 5020:(\t)e24cb004(\t)sub(\t)fp, ip, #4(\t); 0x4
12778 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 +040012779 $Interface_Impl{$LibVersion}{$CurInterface} .= $2."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012780 }
12781 }
12782 }
12783 }
12784}
12785
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012786sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012787{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012788 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012789 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12790 {
12791 if(link_symbol($Symbol, 1, "+Deps"))
12792 { # linker can find a new symbol
12793 # in the old-version library
12794 # So, it's not a new symbol
12795 next;
12796 }
12797 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012798 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012799 next;
12800 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012801 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012802 }
12803}
12804
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012805sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012806{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012807 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012808 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12809 {
12810 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012811 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012812 }
12813 if(link_symbol($Symbol, 2, "+Deps"))
12814 { # linker can find an old symbol
12815 # in the new-version library
12816 next;
12817 }
12818 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012819 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012820 next;
12821 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012822 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012823 }
12824}
12825
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012826sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012827{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012828 my $Level = $_[0];
12829 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012830 { # checking added symbols
12831 next if($CompleteSignature{2}{$Symbol}{"Private"});
12832 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012833 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012834 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012835 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012836 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012837 { # checking removed symbols
12838 next if($CompleteSignature{1}{$Symbol}{"Private"});
12839 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012840 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012841 { # skip v-tables for templates, that should not be imported by applications
12842 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012843 if(my $CName = $VTableClass{$Symbol})
12844 {
12845 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12846 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012847 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012848 next;
12849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012850 }
12851 }
12852 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012853 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012854 }
12855 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12856 { # symbols for pure virtual methods cannot be called by clients
12857 next;
12858 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012859 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012860 }
12861}
12862
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012863sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012864{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012865 my ($LibVersion, $V) = @_;
12866 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12867 return $Cache{"checkDump"}{$LibVersion}{$V};
12868 }
12869 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012870}
12871
12872sub detectAdded_H($)
12873{
12874 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012875 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12876 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012877 if($Level eq "Source")
12878 { # remove symbol version
12879 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12880 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012881
12882 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12883 { # skip artificial constructors
12884 next;
12885 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012886 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012887 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12888 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012889 next;
12890 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012891 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012892 next;
12893 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012894 if(not defined $CompleteSignature{1}{$Symbol}
12895 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12896 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012897 if($UsedDump{2}{"SrcBin"})
12898 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012899 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012900 { # support for old and different (!) ABI dumps
12901 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12902 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012903 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012904 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012905 {
12906 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12907 {
12908 if($Lang eq "C")
12909 { # support for old ABI dumps: missed extern "C" functions
12910 next;
12911 }
12912 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012913 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012914 else
12915 {
12916 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012917 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012918 next;
12919 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012920 }
12921 }
12922 }
12923 }
12924 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012925 }
12926 }
12927}
12928
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012929sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012930{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012931 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012932 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12933 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012934 if($Level eq "Source")
12935 { # remove symbol version
12936 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12937 $Symbol=$SN;
12938 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012939 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12940 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012941 next;
12942 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012943 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012944 next;
12945 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012946 if(not defined $CompleteSignature{2}{$Symbol}
12947 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012948 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012949 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012950 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012951 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012952 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012953 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12954 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012955 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012956 if($CheckHeadersOnly)
12957 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012958 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12959 {
12960 if($Lang eq "C")
12961 { # support for old ABI dumps: missed extern "C" functions
12962 next;
12963 }
12964 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012965 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012966 else
12967 {
12968 if(not link_symbol($Symbol, 1, "-Deps"))
12969 { # skip removed inline symbols
12970 next;
12971 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012972 }
12973 }
12974 }
12975 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012976 if(not checkDump(1, "2.15"))
12977 {
12978 if($Symbol=~/_IT_E\Z/)
12979 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12980 next;
12981 }
12982 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012983 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12984 {
12985 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12986 {
12987 if(defined $Constants{2}{$Short})
12988 {
12989 my $Val = $Constants{2}{$Short}{"Value"};
12990 if(defined $Func_ShortName{2}{$Val})
12991 { # old name defined to new
12992 next;
12993 }
12994 }
12995 }
12996
12997 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012998 $RemovedInt{$Level}{$Symbol} = 1;
12999 if($Level eq "Source")
13000 { # search for a source-compatible equivalent
13001 setAlternative($Symbol, $Level);
13002 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013003 }
13004 }
13005}
13006
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013007sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013008{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013009 my $Level = $_[0];
13010 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013011 { # checking added symbols
13012 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013013 next if($CompleteSignature{2}{$Symbol}{"Private"});
13014 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013015 if($Level eq "Binary")
13016 {
13017 if($CompleteSignature{2}{$Symbol}{"InLine"})
13018 {
13019 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
13020 { # skip inline non-virtual functions
13021 next;
13022 }
13023 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013024 }
13025 else
13026 { # Source
13027 if($SourceAlternative_B{$Symbol}) {
13028 next;
13029 }
13030 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013031 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013032 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013033 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013034 { # checking removed symbols
13035 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013036 next if($CompleteSignature{1}{$Symbol}{"Private"});
13037 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013038 if($Level eq "Binary")
13039 {
13040 if($CompleteSignature{1}{$Symbol}{"InLine"})
13041 {
13042 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13043 { # skip inline non-virtual functions
13044 next;
13045 }
13046 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013047 }
13048 else
13049 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013050 if(my $Alt = $SourceAlternative{$Symbol})
13051 {
13052 if(defined $CompleteSignature{1}{$Alt}
13053 and $CompleteSignature{1}{$Symbol}{"Const"})
13054 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013055 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013056 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013057 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013058 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013059 }
13060 else
13061 { # do NOT show removed symbol
13062 next;
13063 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013064 }
13065 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013066 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013067 }
13068}
13069
13070sub addParamNames($)
13071{
13072 my $LibraryVersion = $_[0];
13073 return if(not keys(%AddIntParams));
13074 my $SecondVersion = $LibraryVersion==1?2:1;
13075 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13076 {
13077 next if(not keys(%{$AddIntParams{$Interface}}));
13078 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013079 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013080 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13081 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013082 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013083 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13084 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13085 {
13086 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13087 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13088 }
13089 }
13090 else {
13091 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13092 }
13093 }
13094 }
13095 }
13096}
13097
13098sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013099{ # detect changed typedefs to show
13100 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013101 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13102 {
13103 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013104 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13105 if(not $BName1 or isAnon($BName1)) {
13106 next;
13107 }
13108 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13109 if(not $BName2 or isAnon($BName2)) {
13110 next;
13111 }
13112 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013113 $ChangedTypedef{$Typedef} = 1;
13114 }
13115 }
13116}
13117
13118sub get_symbol_suffix($$)
13119{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013120 my ($Symbol, $Full) = @_;
13121 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013122 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013123 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013124 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013125 if(not $Full) {
13126 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13127 }
13128 return $Suffix;
13129}
13130
13131sub get_symbol_prefix($$)
13132{
13133 my ($Symbol, $LibVersion) = @_;
13134 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13135 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13136 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013137 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013138 }
13139 return $ShortName;
13140}
13141
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013142sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013143{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013144 my $Symbol = $_[0];
13145 my $PSymbol = $Symbol;
13146 if(not defined $CompleteSignature{2}{$PSymbol}
13147 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13148 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13149 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013150 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013151 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013152 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013153 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013154 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13155 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013156 {
13157 if(defined $CompleteSignature{2}{$PSymbol}
13158 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13159 {
13160 $SourceAlternative{$Symbol} = $PSymbol;
13161 $SourceAlternative_B{$PSymbol} = $Symbol;
13162 if(not defined $CompleteSignature{1}{$PSymbol}
13163 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13164 $SourceReplacement{$Symbol} = $PSymbol;
13165 }
13166 }
13167 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013168 }
13169 else
13170 {
13171 foreach my $Sp ("KV", "VK", "K", "V")
13172 {
13173 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13174 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13175 {
13176 if(defined $CompleteSignature{2}{$PSymbol}
13177 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13178 {
13179 $SourceAlternative{$Symbol} = $PSymbol;
13180 $SourceAlternative_B{$PSymbol} = $Symbol;
13181 if(not defined $CompleteSignature{1}{$PSymbol}
13182 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13183 $SourceReplacement{$Symbol} = $PSymbol;
13184 }
13185 }
13186 }
13187 $PSymbol = $Symbol;
13188 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013189 }
13190 }
13191 }
13192 return "";
13193}
13194
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013195sub getSymKind($$)
13196{
13197 my ($Symbol, $LibVersion) = @_;
13198 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13199 {
13200 return "Global_Data";
13201 }
13202 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13203 {
13204 return "Method";
13205 }
13206 return "Function";
13207}
13208
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013209sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013210{
13211 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013212 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013213
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013214 mergeBases($Level);
13215
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013216 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013217 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013218 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013219 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013220 next;
13221 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013222 if(defined $CompleteSignature{1}{$Symbol}
13223 and $CompleteSignature{1}{$Symbol}{"Header"})
13224 { # double-check added symbol
13225 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013226 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013227 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013228 next;
13229 }
13230 if($Symbol=~/\A(_Z|\?)/)
13231 { # C++
13232 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13233 }
13234 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13235 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013236 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13237 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013238 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013239 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013240 {
13241 if($TName_Tid{1}{$AffectedClass_Name})
13242 { # class should exist in previous version
13243 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13244 { # old v-table is NOT copied by old applications
13245 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13246 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013247 "Target"=>get_Signature($Symbol, 2),
13248 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013249 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013250 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013252 }
13253 }
13254 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013255 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13256 { # check all removed exported symbols
13257 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013258 next;
13259 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013260 if(defined $CompleteSignature{2}{$Symbol}
13261 and $CompleteSignature{2}{$Symbol}{"Header"})
13262 { # double-check removed symbol
13263 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013264 }
13265 if($CompleteSignature{1}{$Symbol}{"Private"})
13266 { # skip private methods
13267 next;
13268 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013269 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013270 next;
13271 }
13272 $CheckedSymbols{$Level}{$Symbol} = 1;
13273 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13274 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013275 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13276 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013277 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013278 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13279 {
13280 if($TName_Tid{2}{$AffectedClass_Name})
13281 { # class should exist in newer version
13282 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13283 { # old v-table is NOT copied by old applications
13284 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13285 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013286 "Target"=>get_Signature($OverriddenMethod, 1),
13287 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013288 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013289 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013291 }
13292 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013293 if($Level eq "Binary"
13294 and $OSgroup eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013295 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013296 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013297 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013298 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013299 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013300 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013301 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013302 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013303 {
13304 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13305 "Target"=>$tr_name{$Symbol},
13306 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013307 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013308 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013309 else
13310 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013311 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013312 "Target"=>$tr_name{$Symbol},
13313 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013314 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013315 }
13316 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013317 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013318 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013319 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013320 {
13321 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13322 "Target"=>$tr_name{$Symbol},
13323 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013324 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013325 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013326 else
13327 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013328 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013329 "Target"=>$tr_name{$Symbol},
13330 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013331 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013332 }
13333 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013334 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13335 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13336 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13337 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13338 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013339 {
13340 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013341 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013342 $ProblemType = "Global_Data_Symbol_Changed_Type";
13343 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013344 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13345 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013346 "Old_Type"=>$RTName1,
13347 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013348 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013349 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013350 }
13351 }
13352 }
13353 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013354 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013355 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013356 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013357 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013358 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013359 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013360 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013361 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13362 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013363 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013364 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013365 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013366 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013367 }
13368 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013369 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13370 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013371 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013372 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013373 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013374 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013375 }
13376 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013377 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013378 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013379 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013380 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013381 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013382 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013383 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013384 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013385 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013386 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013387 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013388 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013389 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013390 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013391 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013392 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013393 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013394 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013395 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013396 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013397 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013398 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013399 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013400 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013401 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013402 { # "volatile" to non-"volatile"
13403
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013404 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013405 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013406 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013407 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013408 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013409 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013410 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013411 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013412 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013413 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013414 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013415 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013416 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013417 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013418 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013419 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013420 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013421 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13422 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013423 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013424 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013425 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013426 }
13427 }
13428 }
13429 }
13430 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013431 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13432 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013433 $CurrentSymbol = $Symbol;
13434
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013435 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13436 if($Level eq "Source")
13437 { # remove symbol version
13438 $Symbol=$SN;
13439 }
13440 else
13441 { # Binary
13442 if(not $SV)
13443 { # symbol without version
13444 if(my $VSym = $SymVer{1}{$Symbol})
13445 { # the symbol is linked with versioned symbol
13446 if($CompleteSignature{2}{$VSym}{"MnglName"})
13447 { # show report for symbol@ver only
13448 next;
13449 }
13450 elsif(not link_symbol($VSym, 2, "-Deps"))
13451 { # changed version: sym@v1 to sym@v2
13452 # do NOT show report for symbol
13453 next;
13454 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013455 }
13456 }
13457 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013458 my $PSymbol = $Symbol;
13459 if($Level eq "Source"
13460 and my $S = $SourceReplacement{$Symbol})
13461 { # take a source-compatible replacement function
13462 $PSymbol = $S;
13463 }
13464 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013465 { # private symbols
13466 next;
13467 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013468 if(not defined $CompleteSignature{1}{$Symbol}
13469 or not defined $CompleteSignature{2}{$PSymbol})
13470 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013471 next;
13472 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013473 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13474 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13475 { # no mangled name
13476 next;
13477 }
13478 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13479 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013480 { # without a header
13481 next;
13482 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013483
13484 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13485 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13486 { # became pure
13487 next;
13488 }
13489 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13490 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13491 { # became non-pure
13492 next;
13493 }
13494
13495 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13496 { # exported, target, inline virtual and pure virtual
13497 next;
13498 }
13499 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13500 { # exported, target, inline virtual and pure virtual
13501 next;
13502 }
13503
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013504 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013505 {
13506 if($CompleteSignature{1}{$Symbol}{"Data"}
13507 and $CompleteSignature{2}{$PSymbol}{"Data"})
13508 {
13509 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13510 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13511 if(defined $Value1)
13512 {
13513 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13514 if(defined $Value2)
13515 {
13516 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13517 if($Value1 ne $Value2)
13518 {
13519 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13520 "Old_Value"=>$Value1,
13521 "New_Value"=>$Value2,
13522 "Target"=>get_Signature($Symbol, 1) );
13523 }
13524 }
13525 }
13526 }
13527 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013528
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013529 if($CompleteSignature{2}{$PSymbol}{"Private"})
13530 {
13531 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13532 "Target"=>get_Signature_M($PSymbol, 2) );
13533 }
13534 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13535 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13536 {
13537 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13538 "Target"=>get_Signature_M($PSymbol, 2) );
13539 }
13540 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13541 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13542 {
13543 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13544 "Target"=>get_Signature_M($PSymbol, 2) );
13545 }
13546
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013547 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013548 mergeVirtualTables($Symbol, $Level);
13549
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013550 if($COMPILE_ERRORS)
13551 { # if some errors occurred at the compiling stage
13552 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013553 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013554 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013555 { # missed information about parameters in newer version
13556 next;
13557 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013558 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013559 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013560 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013561 next;
13562 }
13563 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013564 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013565 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013566 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013567 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13568 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013569 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13570 "Target"=>get_Signature($Symbol, 1)
13571 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013572 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013573 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013574 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13575 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013576 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013577 "Target"=>get_Signature($Symbol, 1)
13578 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013579 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013580 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13581 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013582 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013583 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013584 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013585 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13586 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13587 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013588 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013589 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013590 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13591 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013592 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013593 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013594 my $ProblemType = "Virtual_Method_Position";
13595 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13596 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013597 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013598 if(isUsedClass($Class_Id, 1, $Level))
13599 {
13600 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013601 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013602 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013603 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13604 next;
13605 }
13606 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013607 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013608 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13609 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013610 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013611 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013612 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013613 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013614 }
13615 }
13616 }
13617 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013618 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13619 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013620 { # do NOT check type changes in pure virtuals
13621 next;
13622 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013623 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013624 if($Symbol=~/\A(_Z|\?)/
13625 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013626 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013627 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013628 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013629 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013630 }
13631 }
13632 else
13633 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013634 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013635 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013636 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013637 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13638 last if($PType2_Name eq "...");
13639 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13640 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013641 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013642 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013643 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013644 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13645 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013646 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13647 $ParamPos_Prev = "lost";
13648 }
13649 }
13650 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013651 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013652 }
13653 if($ParamPos_Prev eq "lost")
13654 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013655 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013656 {
13657 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013658 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013659 $ProblemType = "Added_Unnamed_Parameter";
13660 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013661 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013662 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013663 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013664 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013665 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013666 }
13667 else
13668 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013669 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013670 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013671 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013672 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13673 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013674 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013675 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013676 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013677 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013678 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013679 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013680 "Param_Type"=>$PType2_Name,
13681 "Old_Value"=>$PName_Old,
13682 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013683 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013684 }
13685 }
13686 else
13687 {
13688 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013689 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013690 $ProblemType = "Added_Middle_Unnamed_Parameter";
13691 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013692 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013693 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013694 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013695 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013696 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013697 }
13698 }
13699 }
13700 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013701 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013702 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013703 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013704 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013705 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013706 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013707 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013708 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013709 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013710 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13711 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013712 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013713 }
13714 }
13715 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013716 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013717 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013718 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013719 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13720 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013721 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13722 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013723 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013724 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013725 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013726 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13727 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013728 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13729 $ParamPos_New = "lost";
13730 }
13731 }
13732 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013733 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013734 }
13735 if($ParamPos_New eq "lost")
13736 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013737 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013738 {
13739 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013740 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013741 $ProblemType = "Removed_Unnamed_Parameter";
13742 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013743 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013744 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013745 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013746 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013747 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013748 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013749 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013750 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013751 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013752 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013753 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013754 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013755 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013756 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013757 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013758 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013759 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013760 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013761 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013762 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013763 "Old_Value"=>$PName,
13764 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013765 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013766 }
13767 }
13768 else
13769 {
13770 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013771 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013772 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13773 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013774 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013775 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013776 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013777 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013778 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013779 }
13780 }
13781 }
13782 }
13783 }
13784 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013785 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13786 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013787 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013788
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013789 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013790 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013791 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13792 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013793 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013794
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013795 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013796 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013797 if($SubProblemType eq "Return_Type_And_Size") {
13798 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13799 }
13800 elsif($SubProblemType eq "Return_Type_Format") {
13801 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13802 }
13803 else {
13804 $ProblemTypes{"Global_Data_Type"} = 1;
13805 }
13806
13807 # quals
13808 if($SubProblemType eq "Return_Type"
13809 or $SubProblemType eq "Return_Type_And_Size"
13810 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013811 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013812 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13813 { # const to non-const
13814 if($RR==2) {
13815 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13816 }
13817 else {
13818 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13819 }
13820 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013821 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013822 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13823 { # non-const to const
13824 if($RA==2) {
13825 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13826 }
13827 else {
13828 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13829 }
13830 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013831 }
13832 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013833 }
13834 else
13835 {
13836 # quals
13837 if($SubProblemType eq "Return_Type"
13838 or $SubProblemType eq "Return_Type_And_Size"
13839 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013840 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013841 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013842 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013843 if(addedQual($Old_Value, $New_Value, "volatile"))
13844 {
13845 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13846 if($Level ne "Source"
13847 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13848 $ProblemTypes{"Return_Type"} = 1;
13849 }
13850 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013851 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013852 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13853 {
13854 if($RA==2) {
13855 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13856 }
13857 else {
13858 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13859 }
13860 if($Level ne "Source"
13861 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13862 $ProblemTypes{"Return_Type"} = 1;
13863 }
13864 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013865 }
13866 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013867 if($Level eq "Binary"
13868 and not $CompleteSignature{1}{$Symbol}{"Data"})
13869 {
13870 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13871 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13872 { # if one of the architectures is unknown
13873 # then set other arhitecture to unknown too
13874 ($Arch1, $Arch2) = ("unknown", "unknown");
13875 }
13876 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013877 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013878 {
13879 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13880 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13881 }
13882 else
13883 {
13884 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13885 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13886 }
13887
13888 if($SubProblemType eq "Return_Type_Became_Void")
13889 {
13890 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13891 { # parameters stack has been affected
13892 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013893 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013894 }
13895 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013896 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013897 }
13898 }
13899 }
13900 elsif($SubProblemType eq "Return_Type_From_Void")
13901 {
13902 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13903 { # parameters stack has been affected
13904 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013905 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013906 }
13907 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013908 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013909 }
13910 }
13911 }
13912 elsif($SubProblemType eq "Return_Type"
13913 or $SubProblemType eq "Return_Type_And_Size"
13914 or $SubProblemType eq "Return_Type_Format")
13915 {
13916 if($Conv1{"Method"} ne $Conv2{"Method"})
13917 {
13918 if($Conv1{"Method"} eq "stack")
13919 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013920 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013921 }
13922 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013923 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013924 }
13925 }
13926 else
13927 {
13928 if($Conv1{"Method"} eq "reg")
13929 {
13930 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13931 {
13932 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013933 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013934 }
13935 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013936 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013937 }
13938 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013939 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013940 }
13941 }
13942 }
13943 }
13944 }
13945 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013946
13947 if(not keys(%ProblemTypes))
13948 { # default
13949 $ProblemTypes{$SubProblemType} = 1;
13950 }
13951
13952 foreach my $ProblemType (keys(%ProblemTypes))
13953 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013954 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013955 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013956 }
13957 if($ReturnType1_Id and $ReturnType2_Id)
13958 {
13959 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013960 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13961
13962 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013963
13964 if($CompleteSignature{1}{$Symbol}{"Data"})
13965 {
13966 if($Level eq "Binary")
13967 {
13968 if(get_PLevel($ReturnType1_Id, 1)==0)
13969 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013970 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013971 { # add "Global_Data_Size" problem
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013972 my $New_Value = $Sub_SubProblems->{$SubProblemType}{"New_Value"};
13973 my $Old_Value = $Sub_SubProblems->{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013974 if($SubProblemType eq "DataType_Size")
13975 { # add a new problem
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013976 $AddProblems->{"Global_Data_Size"} = $Sub_SubProblems->{$SubProblemType};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013977 }
13978 }
13979 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013980 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013981 {
13982 if(defined $GlobalDataObject{1}{$Symbol}
13983 and defined $GlobalDataObject{2}{$Symbol})
13984 {
13985 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13986 my $New_Size = $GlobalDataObject{2}{$Symbol};
13987 if($Old_Size!=$New_Size)
13988 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013989 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013990 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013991 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013992 }
13993 }
13994 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013995 }
13996 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013997
13998 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013999 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014000 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014001 {
14002 my $NewLocation = ($SubLocation)?"retval->".$SubLocation:"retval";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014003 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
14004 }
14005 }
14006
14007 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
14008 {
14009 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
14010 {
14011 my $NewLocation = ($SubLocation)?"retval->".$SubLocation:"retval";
14012 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014013 }
14014 }
14015 }
14016
14017 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014018 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
14019 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
14020 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014021 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014022 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014023 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
14024 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014025 if($ThisPtr1_Id and $ThisPtr2_Id)
14026 {
14027 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014028 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14029 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014030 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014031 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014032 {
14033 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014034 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014035 }
14036 }
14037 }
14038 }
14039 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014040 if($Level eq "Binary") {
14041 mergeVTables($Level);
14042 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014043 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14044 $CheckedSymbols{$Level}{$Symbol} = 1;
14045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014046}
14047
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014048sub rmQuals($$)
14049{
14050 my ($Value, $Qual) = @_;
14051 if(not $Qual) {
14052 return $Value;
14053 }
14054 if($Qual eq "all")
14055 { # all quals
14056 $Qual = "const|volatile|restrict";
14057 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014058 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014059 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014060 }
14061 return $Value;
14062}
14063
14064sub cmpBTypes($$$$)
14065{
14066 my ($T1, $T2, $V1, $V2) = @_;
14067 $T1 = uncover_typedefs($T1, $V1);
14068 $T2 = uncover_typedefs($T2, $V2);
14069 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14070}
14071
14072sub addedQual($$$)
14073{
14074 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014075 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014076}
14077
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014078sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014079{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014080 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014081 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014082}
14083
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014084sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014085{
14086 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14087 $Old_Value = uncover_typedefs($Old_Value, $V1);
14088 $New_Value = uncover_typedefs($New_Value, $V2);
14089 if($Old_Value eq $New_Value)
14090 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014091 return 0;
14092 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014093 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014094 { # without a qual
14095 return 0;
14096 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014097 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014098 { # became non-qual
14099 return 1;
14100 }
14101 else
14102 {
14103 my @BQ1 = getQualModel($Old_Value, $Qual);
14104 my @BQ2 = getQualModel($New_Value, $Qual);
14105 foreach (0 .. $#BQ1)
14106 { # removed qual
14107 if($BQ1[$_]==1
14108 and $BQ2[$_]!=1)
14109 {
14110 return 2;
14111 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014112 }
14113 }
14114 return 0;
14115}
14116
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014117sub getQualModel($$)
14118{
14119 my ($Value, $Qual) = @_;
14120 if(not $Qual) {
14121 return $Value;
14122 }
14123
14124 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014125 while($Value=~/(\w+)/ and $1 ne $Qual) {
14126 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014127 }
14128 $Value=~s/[^\*\&\w]+//g;
14129
14130 # modeling
14131 # int*const*const == 011
14132 # int**const == 001
14133 my @Model = ();
14134 my @Elems = split(/[\*\&]/, $Value);
14135 if(not @Elems) {
14136 return (0);
14137 }
14138 foreach (@Elems)
14139 {
14140 if($_ eq $Qual) {
14141 push(@Model, 1);
14142 }
14143 else {
14144 push(@Model, 0);
14145 }
14146 }
14147
14148 return @Model;
14149}
14150
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014151my %StringTypes = map {$_=>1} (
14152 "char*",
14153 "char const*"
14154);
14155
14156my %CharTypes = map {$_=>1} (
14157 "char",
14158 "char const"
14159);
14160
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014161sub showVal($$$)
14162{
14163 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014164 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014165 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014166 if(substr($Value, 0, 2) eq "_Z")
14167 {
14168 if(my $Unmangled = $tr_name{$Value}) {
14169 return $Unmangled;
14170 }
14171 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014172 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014173 { # strings
14174 return "\"$Value\"";
14175 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014176 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014177 { # characters
14178 return "\'$Value\'";
14179 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014180 if($Value eq "")
14181 { # other
14182 return "\'\'";
14183 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014184 return $Value;
14185}
14186
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014187sub getRegs($$$)
14188{
14189 my ($LibVersion, $Symbol, $Pos) = @_;
14190
14191 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14192 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014193 my %Regs = ();
14194 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14195 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014196 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014197 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14198 }
14199 }
14200
14201 return join(", ", sort keys(%Regs));
14202 }
14203
14204 return undef;
14205}
14206
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014207sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014208{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014209 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014210 if(not $Symbol) {
14211 return;
14212 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014213 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14214 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14215 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14216 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014217 if(not $PType1_Id
14218 or not $PType2_Id) {
14219 return;
14220 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014221
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014222 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014223 { # do not merge "this"
14224 if($PName1 eq "this" or $PName2 eq "this") {
14225 return;
14226 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014227 }
14228
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014229 my %Type1 = get_Type($PType1_Id, 1);
14230 my %Type2 = get_Type($PType2_Id, 2);
14231 my %BaseType1 = get_BaseType($PType1_Id, 1);
14232 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014233 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014234
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014235 if($Level eq "Binary")
14236 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014237 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014238 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14239 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14240 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14241 {
14242 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014243 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014244 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014245 }
14246 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14247 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14248 {
14249 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014250 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014251 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014253 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014254
14255 if(defined $UsedDump{1}{"DWARF"}
14256 and defined $UsedDump{2}{"DWARF"})
14257 {
14258 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14259 {
14260 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14261 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14262 if($Old_Regs and $New_Regs)
14263 {
14264 if($Old_Regs ne $New_Regs)
14265 {
14266 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14267 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014268 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014269 "Old_Value"=>$Old_Regs,
14270 "New_Value"=>$New_Regs );
14271 }
14272 }
14273 elsif($Old_Regs and not $New_Regs)
14274 {
14275 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14276 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014277 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014278 "Old_Value"=>$Old_Regs );
14279 }
14280 elsif(not $Old_Regs and $New_Regs)
14281 {
14282 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14283 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014284 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014285 "New_Value"=>$New_Regs );
14286 }
14287 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14288 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14289 {
14290 if($Old_Offset ne $New_Offset)
14291 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014292 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14293 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14294
14295 $Old_Offset = $Old_Offset - $Start1;
14296 $New_Offset = $New_Offset - $Start2;
14297
14298 if($Old_Offset ne $New_Offset)
14299 {
14300 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14301 "Target"=>$PName1,
14302 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14303 "Old_Value"=>$Old_Offset,
14304 "New_Value"=>$New_Offset );
14305 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014306 }
14307 }
14308 }
14309 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014310 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014311 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14312 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014313 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014314 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014315 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14316 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014317 if(not checkDump(1, "2.13")
14318 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014319 { # support for old ABI dumps
14320 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014321 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014322 if($Type1{"Name"} eq "bool"
14323 and $Value_Old eq "false" and $Value_New eq "0")
14324 { # int class::method ( bool p = 0 );
14325 # old ABI dumps: "false"
14326 # new ABI dumps: "0"
14327 $Value_Old = "0";
14328 }
14329 }
14330 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014331 if(not checkDump(1, "2.18")
14332 and checkDump(2, "2.18"))
14333 { # support for old ABI dumps
14334 if(not defined $Value_Old
14335 and substr($Value_New, 0, 2) eq "_Z") {
14336 $Value_Old = $Value_New;
14337 }
14338 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014339 if(defined $Value_Old)
14340 {
14341 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14342 if(defined $Value_New)
14343 {
14344 $Value_New = showVal($Value_New, $PType2_Id, 2);
14345 if($Value_Old ne $Value_New)
14346 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014347 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014348 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014349 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014350 "Old_Value"=>$Value_Old,
14351 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014352 }
14353 }
14354 else
14355 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014356 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014357 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014358 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014359 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014360 }
14361 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014362 elsif(defined $Value_New)
14363 {
14364 $Value_New = showVal($Value_New, $PType2_Id, 2);
14365 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14366 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014367 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014368 "New_Value"=>$Value_New );
14369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014370 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014371
14372 if($ChkRnmd)
14373 {
14374 if($PName1 and $PName2 and $PName1 ne $PName2
14375 and $PType1_Id!=-1 and $PType2_Id!=-1
14376 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14377 { # except unnamed "..." value list (Id=-1)
14378 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14379 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014380 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014381 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14382 "Old_Value"=>$PName1,
14383 "New_Value"=>$PName2,
14384 "New_Signature"=>get_Signature($Symbol, 2) );
14385 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014386 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014387
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014388 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014389 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014390
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014391 foreach my $SubProblemType (keys(%SubProblems))
14392 { # add new problems, remove false alarms
14393 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14394 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014395
14396 # quals
14397 if($SubProblemType eq "Parameter_Type"
14398 or $SubProblemType eq "Parameter_Type_And_Size"
14399 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014400 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014401 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014402 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014403 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014404 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014405 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014406 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14407 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14408 }
14409 }
14410 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14411 {
14412 if(removedQual($Old_Value, $New_Value, "volatile")) {
14413 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014414 }
14415 }
14416 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14417 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14418 { # int to "int const"
14419 delete($SubProblems{$SubProblemType});
14420 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014421 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014422 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14423 { # "int const" to int
14424 delete($SubProblems{$SubProblemType});
14425 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014426 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14427 { # "const" to non-"const"
14428 if($RR==2) {
14429 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14430 }
14431 else {
14432 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14433 }
14434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014435 }
14436 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014437
14438 if($Level eq "Source")
14439 {
14440 foreach my $SubProblemType (keys(%SubProblems))
14441 {
14442 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14443 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14444
14445 if($SubProblemType eq "Parameter_Type")
14446 {
14447 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14448 delete($SubProblems{$SubProblemType});
14449 }
14450 }
14451 }
14452 }
14453
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014454 foreach my $SubProblemType (keys(%SubProblems))
14455 { # modify/register problems
14456 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14457 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014458 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14459 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014460
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014461 my $NewProblemType = $SubProblemType;
14462 if($Old_Value eq "..." and $New_Value ne "...")
14463 { # change from "..." to "int"
14464 if($ParamPos1==0)
14465 { # ISO C requires a named argument before "..."
14466 next;
14467 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014468 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014469 }
14470 elsif($New_Value eq "..." and $Old_Value ne "...")
14471 { # change from "int" to "..."
14472 if($ParamPos2==0)
14473 { # ISO C requires a named argument before "..."
14474 next;
14475 }
14476 $NewProblemType = "Parameter_Became_VaList";
14477 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014478 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014479 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014480 {
14481 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014482 if($Arch1 eq "unknown"
14483 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014484 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014485 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014486 ($Arch1, $Arch2) = ("unknown", "unknown");
14487 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014488 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014489 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014490 { # real
14491 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14492 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14493 }
14494 else
14495 { # model
14496 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14497 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14498 }
14499 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014500 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014501 if($Conv1{"Method"} eq "stack")
14502 {
14503 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14504 $NewProblemType = "Parameter_Type_And_Stack";
14505 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014506 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014507 elsif($Conv1{"Method"} eq "reg")
14508 {
14509 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14510 $NewProblemType = "Parameter_Type_And_Register";
14511 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014512 }
14513 }
14514 else
14515 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014516 if($Conv1{"Method"} eq "stack") {
14517 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014518 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014519 elsif($Conv1{"Method"} eq "register") {
14520 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014521 }
14522 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014523 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14524 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014525 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014526 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014527 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014528 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014529 "New_Signature"=>get_Signature($Symbol, 2) );
14530 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014531 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014532
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014533 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014534
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014535 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014536 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14537 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014538 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014539 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014540 {
14541 my $NewProblemType = $SubProblemType;
14542 if($SubProblemType eq "DataType_Size")
14543 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014544 if($Type1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014545 { # stack has been affected
14546 $NewProblemType = "DataType_Size_And_Stack";
14547 }
14548 }
14549 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014550 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014551 }
14552 }
14553}
14554
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014555sub find_ParamPair_Pos_byName($$$)
14556{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014557 my ($Name, $Symbol, $LibVersion) = @_;
14558 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014559 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014560 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14561 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014562 {
14563 return $ParamPos;
14564 }
14565 }
14566 return "lost";
14567}
14568
14569sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14570{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014571 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014572 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014573 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014574 {
14575 next if($Order eq "backward" and $ParamPos>$MediumPos);
14576 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014577 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14578 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014579 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014580 push(@Positions, $ParamPos);
14581 }
14582 }
14583 return @Positions;
14584}
14585
14586sub getTypeIdByName($$)
14587{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014588 my ($TypeName, $LibVersion) = @_;
14589 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014590}
14591
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014592sub diffTypes($$$)
14593{
14594 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14595 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14596 }
14597 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14598 { # skip recursive declarations
14599 return 0;
14600 }
14601
14602 pushType($_[0], $_[1], \@RecurTypes_Diff);
14603 my $Diff = diffTypes_I(@_);
14604 pop(@RecurTypes_Diff);
14605
14606 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14607}
14608
14609sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014610{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014611 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014612
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014613 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14614 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014615
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014616 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14617 { # equal types
14618 return 0;
14619 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014620 if($Type1_Pure{"Name"} eq "void")
14621 { # from void* to something
14622 return 0;
14623 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014624 if($Type1_Pure{"Name"}=~/\*/
14625 or $Type2_Pure{"Name"}=~/\*/)
14626 { # compared in detectTypeChange()
14627 return 0;
14628 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014629
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014630 my %FloatType = map {$_=>1} (
14631 "float",
14632 "double",
14633 "long double"
14634 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014635
14636 my $T1 = $Type1_Pure{"Type"};
14637 my $T2 = $Type2_Pure{"Type"};
14638
14639 if($T1 eq "Struct"
14640 and $T2 eq "Class")
14641 { # compare as data structures
14642 $T2 = "Struct";
14643 }
14644
14645 if($T1 eq "Class"
14646 and $T2 eq "Struct")
14647 { # compare as data structures
14648 $T1 = "Struct";
14649 }
14650
14651 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014652 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014653 if($T1 eq "Intrinsic"
14654 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014655 { # "int" to "enum"
14656 return 0;
14657 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014658 elsif($T2 eq "Intrinsic"
14659 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014660 { # "enum" to "int"
14661 return 0;
14662 }
14663 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014664 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014665 # ...
14666 return 1;
14667 }
14668 }
14669 else
14670 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014671 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014672 {
14673 if($FloatType{$Type1_Pure{"Name"}}
14674 or $FloatType{$Type2_Pure{"Name"}})
14675 { # "float" to "double"
14676 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014677 if($Level eq "Source")
14678 { # Safe
14679 return 0;
14680 }
14681 else {
14682 return 1;
14683 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014684 }
14685 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014686 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014687 {
14688 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14689 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014690 if(not @Membs1
14691 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014692 { # private
14693 return 0;
14694 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014695 if($#Membs1!=$#Membs2)
14696 { # different number of elements
14697 return 1;
14698 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014699 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014700 {
14701 foreach my $Pos (@Membs1)
14702 { # compare elements by name and value
14703 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14704 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14705 { # different names
14706 return 1;
14707 }
14708 }
14709 }
14710 else
14711 {
14712 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014713 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014714 if($Level eq "Source")
14715 {
14716 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14717 { # different names
14718 return 1;
14719 }
14720 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014721
14722 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14723 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14724
14725 if($MT1{"Name"} ne $MT2{"Name"}
14726 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14727 {
14728 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14729 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14730
14731 if($PL1 ne $PL2)
14732 { # different pointer level
14733 return 1;
14734 }
14735
14736 # compare base types
14737 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14738 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14739
14740 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14741 { # different types
14742 return 1;
14743 }
14744 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014745 }
14746 }
14747 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014748 else
14749 {
14750 # TODO: arrays, etc.
14751 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014752 }
14753 return 0;
14754}
14755
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014756sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014757{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014758 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014759 if(not $Type1_Id or not $Type2_Id) {
14760 return ();
14761 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014762 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014763 my %Type1 = get_Type($Type1_Id, 1);
14764 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014765 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14766 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14767 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14768 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 +040014769
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014770 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14771 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014772 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14773 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14774 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14775 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14776 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14777 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14778 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014779 if($Type1{"Name"} eq $Type2{"Name"})
14780 {
14781 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14782 { # will be reported in mergeTypes() as typedef problem
14783 return ();
14784 }
14785 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14786 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14787 if(%Typedef_1 and %Typedef_2)
14788 {
14789 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14790 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14791 { # const Typedef
14792 return ();
14793 }
14794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014795 }
14796 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14797 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014798 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014799 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14800 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014801 {
14802 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14803 "Old_Value"=>$Type1_Base{"Name"},
14804 "New_Value"=>$Type2_Base{"Name"},
14805 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014806 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014807 }
14808 else
14809 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014810 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014811 { # format change
14812 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14813 "Old_Value"=>$Type1_Base{"Name"},
14814 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014815 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014816 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014817 }
14818 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14819 {
14820 %{$LocalProblems{$Prefix."_BaseType"}}=(
14821 "Old_Value"=>$Type1_Base{"Name"},
14822 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014823 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014824 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014825 }
14826 }
14827 }
14828 }
14829 elsif($Type1{"Name"} ne $Type2{"Name"})
14830 { # type change
14831 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14832 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014833 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014834 and $Type1_Pure{"Name"} eq "void")
14835 {
14836 %{$LocalProblems{"Return_Type_From_Void"}}=(
14837 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014838 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014839 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014840 elsif($Prefix eq "Return"
14841 and $Type2_Pure{"Name"} eq "void")
14842 {
14843 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14844 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014845 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014846 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014847 else
14848 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014849 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014850 and $Type1{"Size"} and $Type2{"Size"}
14851 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014852 {
14853 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14854 "Old_Value"=>$Type1{"Name"},
14855 "New_Value"=>$Type2{"Name"},
14856 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014857 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014858 }
14859 else
14860 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014861 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014862 { # format change
14863 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14864 "Old_Value"=>$Type1{"Name"},
14865 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014866 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014867 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014868 }
14869 elsif(tNameLock($Type1_Id, $Type2_Id))
14870 { # FIXME: correct this condition
14871 %{$LocalProblems{$Prefix."_Type"}}=(
14872 "Old_Value"=>$Type1{"Name"},
14873 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014874 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014875 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014876 }
14877 }
14878 }
14879 }
14880 }
14881 if($Type1_PLevel!=$Type2_PLevel)
14882 {
14883 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14884 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14885 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014886 if($Level eq "Source")
14887 {
14888 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014889 "Old_Value"=>$Type1_PLevel,
14890 "New_Value"=>$Type2_PLevel);
14891 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014892 else
14893 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014894 if($Type2_PLevel>$Type1_PLevel)
14895 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014896 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14897 "Old_Value"=>$Type1_PLevel,
14898 "New_Value"=>$Type2_PLevel);
14899 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014900 else
14901 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014902 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14903 "Old_Value"=>$Type1_PLevel,
14904 "New_Value"=>$Type2_PLevel);
14905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014906 }
14907 }
14908 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014909 if($Type1_Pure{"Type"} eq "Array"
14910 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014911 { # base_type[N] -> base_type[N]
14912 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014913 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014914 foreach my $SubProblemType (keys(%SubProblems))
14915 {
14916 $SubProblemType=~s/_Type/_BaseType/g;
14917 next if(defined $LocalProblems{$SubProblemType});
14918 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14919 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14920 }
14921 }
14922 }
14923 return %LocalProblems;
14924}
14925
14926sub tNameLock($$)
14927{
14928 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014929 my $Changed = 0;
14930 if(differentDumps("G"))
14931 { # different GCC versions
14932 $Changed = 1;
14933 }
14934 elsif(differentDumps("V"))
14935 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014936 if(not checkDump(1, "2.20")
14937 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014938 { # latest names update
14939 # 2.6: added restrict qualifier
14940 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014941 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014942 $Changed = 1;
14943 }
14944 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014945
14946 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14947 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14948
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014949 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014950 { # different formats
14951 if($UseOldDumps)
14952 { # old dumps
14953 return 0;
14954 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014955
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014956 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14957 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014958
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014959 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014960 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014961 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014962 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014963 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014964 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014965 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014966 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014967 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14968 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14969 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014970 { # equal base types
14971 return 0;
14972 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014973
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014974 if(not checkDump(1, "2.13")
14975 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014976 { # broken array names in ABI dumps < 2.13
14977 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014978 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014979 return 0;
14980 }
14981 }
14982
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014983 if(not checkDump(1, "2.6")
14984 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014985 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014986 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014987 and $TN2=~/\brestrict\b/) {
14988 return 0;
14989 }
14990 }
14991
14992 if(not checkDump(1, "2.20")
14993 or not checkDump(2, "2.20"))
14994 { # added restrict attribute in 2.6
14995 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14996 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014997 return 0;
14998 }
14999 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015000 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015001 else
15002 {
15003 # typedef struct {...} type_t
15004 # typedef struct type_t {...} type_t
15005 if(index($TN1, " ".$TN2)!=-1)
15006 {
15007 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15008 return 0;
15009 }
15010 }
15011 if(index($TN2, " ".$TN1)!=-1)
15012 {
15013 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15014 return 0;
15015 }
15016 }
15017 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015018 return 1;
15019}
15020
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015021sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015022{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015023 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015024 if(defined $Cache{"differentDumps"}{$Check}) {
15025 return $Cache{"differentDumps"}{$Check};
15026 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015027 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015028 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015029 if($Check eq "G")
15030 {
15031 if(getGccVersion(1) ne getGccVersion(2))
15032 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015033 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015034 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015035 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015036 if($Check eq "V")
15037 {
15038 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15039 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15040 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015041 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015042 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015043 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015044 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015045 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015046}
15047
15048sub formatVersion($$)
15049{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015050 my ($V, $Digits) = @_;
15051 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015052 return join(".", splice(@Elems, 0, $Digits));
15053}
15054
15055sub htmlSpecChars($)
15056{
15057 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015058 if(not $Str) {
15059 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015060 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015061 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15062 $Str=~s/</&lt;/g;
15063 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15064 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015065 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15066 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015067 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015068 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015069 $Str=~s/\n/<br\/>/g;
15070 $Str=~s/\"/&quot;/g;
15071 $Str=~s/\'/&#39;/g;
15072 return $Str;
15073}
15074
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015075sub xmlSpecChars($)
15076{
15077 my $Str = $_[0];
15078 if(not $Str) {
15079 return $Str;
15080 }
15081
15082 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15083 $Str=~s/</&lt;/g;
15084 $Str=~s/>/&gt;/g;
15085
15086 $Str=~s/\"/&quot;/g;
15087 $Str=~s/\'/&#39;/g;
15088
15089 return $Str;
15090}
15091
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015092sub xmlSpecChars_R($)
15093{
15094 my $Str = $_[0];
15095 if(not $Str) {
15096 return $Str;
15097 }
15098
15099 $Str=~s/&amp;/&/g;
15100 $Str=~s/&lt;/</g;
15101 $Str=~s/&gt;/>/g;
15102
15103 $Str=~s/&quot;/"/g;
15104 $Str=~s/&#39;/'/g;
15105
15106 return $Str;
15107}
15108
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015109sub black_name($)
15110{
15111 my $Name = $_[0];
15112 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15113}
15114
15115sub highLight_Signature($)
15116{
15117 my $Signature = $_[0];
15118 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15119}
15120
15121sub highLight_Signature_Italic_Color($)
15122{
15123 my $Signature = $_[0];
15124 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15125}
15126
15127sub separate_symbol($)
15128{
15129 my $Symbol = $_[0];
15130 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15131 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15132 ($Name, $Spec, $Ver) = ($1, $2, $3);
15133 }
15134 return ($Name, $Spec, $Ver);
15135}
15136
15137sub cut_f_attrs($)
15138{
15139 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15140 return $2;
15141 }
15142 return "";
15143}
15144
15145sub highLight_Signature_PPos_Italic($$$$$)
15146{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015147 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15148 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015149 if($CheckObjectsOnly) {
15150 $ItalicParams=$ColorParams=0;
15151 }
15152 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15153 my $Return = "";
15154 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15155 $Return = $2;
15156 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015157 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015158 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015159 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015160 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015161 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015162 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015163 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015164 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015165 }
15166 return $Signature;
15167 }
15168 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15169 $Begin.=" " if($Begin!~/ \Z/);
15170 $End = cut_f_attrs($Signature);
15171 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015172 my ($Short, $Params) = split_Signature($Signature);
15173 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015174 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015175 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015176 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015177 $Part=~s/\A\s+|\s+\Z//g;
15178 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15179 if($Part=~/\([\*]+(\w+)\)/i) {
15180 $ParamName = $1;#func-ptr
15181 }
15182 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15183 $ParamName = $1;
15184 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015185 if(not $ParamName)
15186 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015187 push(@Parts, $Part_Styled);
15188 next;
15189 }
15190 if($ItalicParams and not $TName_Tid{1}{$Part}
15191 and not $TName_Tid{2}{$Part})
15192 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015193 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015194 if($Param_Pos ne ""
15195 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015196 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015197 }
15198 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015199 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015200 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015201 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015202 }
15203 $Part_Styled=~s/,(\w)/, $1/g;
15204 push(@Parts, $Part_Styled);
15205 }
15206 if(@Parts)
15207 {
15208 foreach my $Num (0 .. $#Parts)
15209 {
15210 if($Num==$#Parts)
15211 { # add ")" to the last parameter
15212 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15213 }
15214 elsif(length($Parts[$Num])<=45) {
15215 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15216 }
15217 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015218 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015219 }
15220 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015221 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015222 }
15223 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015224 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015225 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015226 $Signature=~s!\[\]![&#160;]!g;
15227 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015228 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15229 if($SymbolVersion) {
15230 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15231 }
15232 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015233}
15234
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015235sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015236{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015237 my $Signature = $_[0];
15238 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15239 {
15240 $Signature=~s/\A\Q$ShortName\E\(//g;
15241 cut_f_attrs($Signature);
15242 $Signature=~s/\)\Z//;
15243 return ($ShortName, $Signature);
15244 }
15245
15246 # error
15247 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015248}
15249
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015250sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015251{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015252 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015253 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015254 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15255 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015256 foreach my $Pos (0 .. length($Params) - 1)
15257 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015258 my $S = substr($Params, $Pos, 1);
15259 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015260 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015261 }
15262 if($S eq "," and
15263 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015264 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015265 if($Comma)
15266 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015267 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015268 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015269 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015270 }
15271 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015272 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015273 }
15274 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015275 if(not $Sp)
15276 { # remove spaces
15277 foreach (@Parts)
15278 {
15279 s/\A //g;
15280 s/ \Z//g;
15281 }
15282 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015283 return @Parts;
15284}
15285
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015286sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015287{
15288 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015289 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015290 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015291 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15292 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015293 $Center+=length($1);
15294 }
15295 foreach my $Pos (0 .. length($Sign)-1)
15296 {
15297 my $S = substr($Sign, $Pos, 1);
15298 if($S eq $Target)
15299 {
15300 if($B{"("}==$B{")"}
15301 and $B{"<"}==$B{">"}) {
15302 return $Center;
15303 }
15304 }
15305 if(defined $B{$S}) {
15306 $B{$S}+=1;
15307 }
15308 $Center+=1;
15309 }
15310 return 0;
15311}
15312
15313sub appendFile($$)
15314{
15315 my ($Path, $Content) = @_;
15316 return if(not $Path);
15317 if(my $Dir = get_dirname($Path)) {
15318 mkpath($Dir);
15319 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015320 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015321 print FILE $Content;
15322 close(FILE);
15323}
15324
15325sub writeFile($$)
15326{
15327 my ($Path, $Content) = @_;
15328 return if(not $Path);
15329 if(my $Dir = get_dirname($Path)) {
15330 mkpath($Dir);
15331 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015332 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015333 print FILE $Content;
15334 close(FILE);
15335}
15336
15337sub readFile($)
15338{
15339 my $Path = $_[0];
15340 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015341 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015342 local $/ = undef;
15343 my $Content = <FILE>;
15344 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015345 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015346 $Content=~s/\r/\n/g;
15347 }
15348 return $Content;
15349}
15350
15351sub get_filename($)
15352{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015353 if(defined $Cache{"get_filename"}{$_[0]}) {
15354 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015355 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015356 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15357 return ($Cache{"get_filename"}{$_[0]}=$1);
15358 }
15359 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015360}
15361
15362sub get_dirname($)
15363{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015364 if(defined $Cache{"get_dirname"}{$_[0]}) {
15365 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015366 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015367 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15368 return ($Cache{"get_dirname"}{$_[0]}=$1);
15369 }
15370 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015371}
15372
15373sub separate_path($) {
15374 return (get_dirname($_[0]), get_filename($_[0]));
15375}
15376
15377sub esc($)
15378{
15379 my $Str = $_[0];
15380 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15381 return $Str;
15382}
15383
15384sub readLineNum($$)
15385{
15386 my ($Path, $Num) = @_;
15387 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015388 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015389 foreach (1 ... $Num) {
15390 <FILE>;
15391 }
15392 my $Line = <FILE>;
15393 close(FILE);
15394 return $Line;
15395}
15396
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015397sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015398{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015399 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015400 return () if(not $Path or not -f $Path);
15401 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015402 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15403 {
15404 foreach my $AttrVal (split(/;/, $1))
15405 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015406 if($AttrVal=~/(.+):(.+)/)
15407 {
15408 my ($Name, $Value) = ($1, $2);
15409 $Attributes{$Name} = $Value;
15410 }
15411 }
15412 }
15413 return \%Attributes;
15414}
15415
15416sub is_abs($) {
15417 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15418}
15419
15420sub get_abs_path($)
15421{ # abs_path() should NOT be called for absolute inputs
15422 # because it can change them
15423 my $Path = $_[0];
15424 if(not is_abs($Path)) {
15425 $Path = abs_path($Path);
15426 }
15427 return $Path;
15428}
15429
15430sub get_OSgroup()
15431{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015432 my $N = $Config{"osname"};
15433 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015434 return "macos";
15435 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015436 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015437 return "bsd";
15438 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015439 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015440 return "beos";
15441 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015442 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015443 return "symbian";
15444 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015445 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015446 return "windows";
15447 }
15448 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015449 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015450 }
15451}
15452
15453sub getGccVersion($)
15454{
15455 my $LibVersion = $_[0];
15456 if($GCC_VERSION{$LibVersion})
15457 { # dump version
15458 return $GCC_VERSION{$LibVersion};
15459 }
15460 elsif($UsedDump{$LibVersion}{"V"})
15461 { # old-version dumps
15462 return "unknown";
15463 }
15464 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15465 if(not $GccVersion) {
15466 return "unknown";
15467 }
15468 return $GccVersion;
15469}
15470
15471sub showArch($)
15472{
15473 my $Arch = $_[0];
15474 if($Arch eq "arm"
15475 or $Arch eq "mips") {
15476 return uc($Arch);
15477 }
15478 return $Arch;
15479}
15480
15481sub getArch($)
15482{
15483 my $LibVersion = $_[0];
15484 if($CPU_ARCH{$LibVersion})
15485 { # dump version
15486 return $CPU_ARCH{$LibVersion};
15487 }
15488 elsif($UsedDump{$LibVersion}{"V"})
15489 { # old-version dumps
15490 return "unknown";
15491 }
15492 if(defined $Cache{"getArch"}{$LibVersion}) {
15493 return $Cache{"getArch"}{$LibVersion};
15494 }
15495 my $Arch = get_dumpmachine($GCC_PATH); # host version
15496 if(not $Arch) {
15497 return "unknown";
15498 }
15499 if($Arch=~/\A([\w]{3,})(-|\Z)/) {
15500 $Arch = $1;
15501 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040015502 $Arch = "x86" if($Arch=~/\Ai[3-7]86\Z/i);
15503 $Arch = "x86_64" if($Arch=~/\Aamd64\Z/i);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040015504 if($OSgroup eq "windows")
15505 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015506 $Arch = "x86" if($Arch=~/win32|mingw32/i);
15507 $Arch = "x86_64" if($Arch=~/win64|mingw64/i);
15508 }
15509 $Cache{"getArch"}{$LibVersion} = $Arch;
15510 return $Arch;
15511}
15512
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015513sub get_Report_Header($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015514{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015515 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015516 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015517 if(getArch(1) ne getArch(2)
15518 or getArch(1) eq "unknown"
15519 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015520 { # don't show architecture in the header
15521 $ArchInfo="";
15522 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015523 my $Report_Header = "<h1><span class='nowrap'>";
15524 if($Level eq "Source") {
15525 $Report_Header .= "Source compatibility";
15526 }
15527 elsif($Level eq "Binary") {
15528 $Report_Header .= "Binary compatibility";
15529 }
15530 else {
15531 $Report_Header .= "API compatibility";
15532 }
15533 $Report_Header .= " report for the <span style='color:Blue;'>$TargetLibraryFName</span> $TargetComponent</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015534 $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>";
15535 if($AppPath) {
15536 $Report_Header .= " <span class='nowrap'>&#160;(relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)</span>";
15537 }
15538 $Report_Header .= "</h1>\n";
15539 return $Report_Header;
15540}
15541
15542sub get_SourceInfo()
15543{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015544 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015545 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015546 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015547 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015548 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015549 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15550 $CheckedHeaders .= "<div class='h_list'>\n";
15551 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15552 {
15553 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15554 my $Name = get_filename($Identity);
15555 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15556 $CheckedHeaders .= $Name.$Comment."<br/>\n";
15557 }
15558 $CheckedHeaders .= "</div>\n";
15559 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015560 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015561
15562 if(my @Sources = keys(%{$Registered_Sources{1}}))
15563 {
15564 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15565 $CheckedSources .= "<div class='h_list'>\n";
15566 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15567 {
15568 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15569 my $Name = get_filename($Identity);
15570 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15571 $CheckedSources .= $Name.$Comment."<br/>\n";
15572 }
15573 $CheckedSources .= "</div>\n";
15574 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015576 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015577 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015578 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015579 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015580 $CheckedLibs .= "<div class='lib_list'>\n";
15581 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15582 {
15583 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15584 $CheckedLibs .= $Library."<br/>\n";
15585 }
15586 $CheckedLibs .= "</div>\n";
15587 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015588 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015589 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15590}
15591
15592sub get_ObjTitle()
15593{
15594 if(defined $UsedDump{1}{"DWARF"}) {
15595 return "Objects";
15596 }
15597 else {
15598 return ucfirst($SLIB_TYPE)." Libraries";
15599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015600}
15601
15602sub get_TypeProblems_Count($$$)
15603{
15604 my ($TypeChanges, $TargetPriority, $Level) = @_;
15605 my $Type_Problems_Count = 0;
15606 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15607 {
15608 my %Kinds_Target = ();
15609 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15610 {
15611 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15612 {
15613 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015614 my $Priority = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015615 next if($Priority ne $TargetPriority);
15616 if($Kinds_Target{$Kind}{$Target}) {
15617 next;
15618 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015619 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015620 { # select a problem with the highest priority
15621 next;
15622 }
15623 $Kinds_Target{$Kind}{$Target} = 1;
15624 $Type_Problems_Count += 1;
15625 }
15626 }
15627 }
15628 return $Type_Problems_Count;
15629}
15630
15631sub get_Summary($)
15632{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015633 my $Level = $_[0];
15634 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015635 $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 +040015636 %{$RESULT{$Level}} = (
15637 "Problems"=>0,
15638 "Warnings"=>0,
15639 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015640 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015641 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015642 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015643 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015644 {
15645 if(not defined $CompatRules{$Level}{$Kind})
15646 { # unknown rule
15647 if(not $UnknownRules{$Level}{$Kind})
15648 { # only one warning
15649 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15650 $UnknownRules{$Level}{$Kind}=1;
15651 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015652 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015653 }
15654 }
15655 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015656 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15657 {
15658 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15659 {
15660 if(not defined $CompatRules{$Level}{$Kind})
15661 { # unknown rule
15662 if(not $UnknownRules{$Level}{$Kind})
15663 { # only one warning
15664 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15665 $UnknownRules{$Level}{$Kind}=1;
15666 }
15667 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15668 }
15669 }
15670 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015671 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015672 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015673 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015674 {
15675 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15676 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015677 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015678 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015679 my $Priority = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015680 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015681 $Added += 1;
15682 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015683 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015684 {
15685 $Removed += 1;
15686 $TotalAffected{$Level}{$Interface} = $Priority;
15687 }
15688 else
15689 {
15690 if($Priority eq "Safe") {
15691 $I_Other += 1;
15692 }
15693 elsif($Priority eq "High") {
15694 $I_Problems_High += 1;
15695 }
15696 elsif($Priority eq "Medium") {
15697 $I_Problems_Medium += 1;
15698 }
15699 elsif($Priority eq "Low") {
15700 $I_Problems_Low += 1;
15701 }
15702 if(($Priority ne "Low" or $StrictCompat)
15703 and $Priority ne "Safe") {
15704 $TotalAffected{$Level}{$Interface} = $Priority;
15705 }
15706 }
15707 }
15708 }
15709 }
15710 }
15711 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015712 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015713 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015714 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015715 {
15716 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15717 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015718 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015719 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015720 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15721 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015722 my $Priority = $CompatRules{$Level}{$Kind}{"Severity"};
15723 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15724
15725 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Priority})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015726 { # select a problem with the highest priority
15727 next;
15728 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015729
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015730 if(($Priority ne "Low" or $StrictCompat)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015731 and $Priority ne "Safe")
15732 {
15733 if(defined $TotalAffected{$Level}{$Interface})
15734 {
15735 if($Severity_Val{$Priority}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15736 $TotalAffected{$Level}{$Interface} = $Priority;
15737 }
15738 }
15739 else {
15740 $TotalAffected{$Level}{$Interface} = $Priority;
15741 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015742 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015743
15744 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15745
15746 if($MaxSeverity)
15747 {
15748 if($Severity_Val{$Priority}>$Severity_Val{$MaxSeverity}) {
15749 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Priority;
15750 }
15751 }
15752 else {
15753 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Priority;
15754 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015755 }
15756 }
15757 }
15758 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015759
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015760 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15761 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15762 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15763 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015764
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015765 %TypeChanges = (); # free memory
15766
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015767 if($CheckObjectsOnly)
15768 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015769 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015770 }
15771 else
15772 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015773 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015774 if($ExtendedCheck)
15775 { # don't count external_func_0 for constants
15776 $SCount-=1;
15777 }
15778 if($SCount)
15779 {
15780 my %Weight = (
15781 "High" => 100,
15782 "Medium" => 50,
15783 "Low" => 25
15784 );
15785 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015786 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015787 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015788 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015789 }
15790 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015791 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015792 }
15793 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015794 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15795 if($RESULT{$Level}{"Affected"}>=100) {
15796 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015797 }
15798
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015799 $RESULT{$Level}{"Problems"} += $Removed;
15800 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015801 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015802 if($StrictCompat) {
15803 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15804 }
15805 else {
15806 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015808
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015809 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015810 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015811 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015812 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015813 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015814 if($Severity eq "Safe")
15815 {
15816 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015817 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015818 elsif($Severity eq "Low")
15819 {
15820 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015821 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015822 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015823 }
15824
15825 if($C_Problems_Low)
15826 {
15827 if($StrictCompat) {
15828 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15829 }
15830 else {
15831 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015832 }
15833 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015834 if($CheckImpl and $Level eq "Binary")
15835 {
15836 if($StrictCompat) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015837 $RESULT{$Level}{"Problems"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015838 }
15839 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015840 $RESULT{$Level}{"Warnings"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015841 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015842 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015843 if($RESULT{$Level}{"Problems"}
15844 and $RESULT{$Level}{"Affected"}) {
15845 $RESULT{$Level}{"Verdict"} = "incompatible";
15846 }
15847 else {
15848 $RESULT{$Level}{"Verdict"} = "compatible";
15849 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015850
15851 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15852 if(not $TotalTypes)
15853 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015854 $TotalTypes = keys(%{$TName_Tid{1}});
15855 }
15856
15857 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15858 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15859
15860 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15861
15862 if($ReportFormat eq "xml")
15863 { # XML
15864 # test info
15865 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15866 $TestInfo .= " <version1>\n";
15867 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
15868 $TestInfo .= " <architecture>$Arch1</architecture>\n";
15869 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15870 $TestInfo .= " </version1>\n";
15871
15872 $TestInfo .= " <version2>\n";
15873 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
15874 $TestInfo .= " <architecture>$Arch2</architecture>\n";
15875 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15876 $TestInfo .= " </version2>\n";
15877 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15878
15879 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015880 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015881 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015882 $TestResults .= " <headers>\n";
15883 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15884 {
15885 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15886 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15887 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15888 }
15889 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015890 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015891
15892 if(my @Sources = keys(%{$Registered_Sources{1}}))
15893 {
15894 $TestResults .= " <sources>\n";
15895 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15896 {
15897 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15898 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15899 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15900 }
15901 $TestResults .= " </sources>\n";
15902 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015903
15904 $TestResults .= " <libs>\n";
15905 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15906 {
15907 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15908 $TestResults .= " <name>$Library</name>\n";
15909 }
15910 $TestResults .= " </libs>\n";
15911
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015912 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015913 $TestResults .= " <types>".$TotalTypes."</types>\n";
15914
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015915 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15916 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015917 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15918
15919 # problem summary
15920 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15921 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15922
15923 $Problem_Summary .= " <problems_with_types>\n";
15924 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15925 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15926 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15927 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15928 $Problem_Summary .= " </problems_with_types>\n";
15929
15930 $Problem_Summary .= " <problems_with_symbols>\n";
15931 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15932 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15933 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015934 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015935 $Problem_Summary .= " </problems_with_symbols>\n";
15936
15937 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015938 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015939 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015940 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015941 {
15942 $Problem_Summary .= " <impl>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015943 $Problem_Summary .= " <low>".keys(%CompatProblems_Impl)."</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015944 $Problem_Summary .= " </impl>\n";
15945 }
15946 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15947
15948 return ($TestInfo.$TestResults.$Problem_Summary, "");
15949 }
15950 else
15951 { # HTML
15952 # test info
15953 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015954 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015955 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetLibraryFName</td></tr>\n";
15956
15957 my (@VInf1, @VInf2, $AddTestInfo) = ();
15958 if($Arch1 ne "unknown"
15959 and $Arch2 ne "unknown")
15960 { # CPU arch
15961 if($Arch1 eq $Arch2)
15962 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015963 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015964 }
15965 else
15966 { # go to the version number
15967 push(@VInf1, showArch($Arch1));
15968 push(@VInf2, showArch($Arch2));
15969 }
15970 }
15971 if($GccV1 ne "unknown"
15972 and $GccV2 ne "unknown"
15973 and $OStarget ne "windows")
15974 { # GCC version
15975 if($GccV1 eq $GccV2)
15976 { # go to the separate section
15977 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15978 }
15979 else
15980 { # go to the version number
15981 push(@VInf1, "gcc ".$GccV1);
15982 push(@VInf2, "gcc ".$GccV2);
15983 }
15984 }
15985 # show long version names with GCC version and CPU architecture name (if different)
15986 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15987 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15988 $TestInfo .= $AddTestInfo;
15989 #if($COMMON_LANGUAGE{1}) {
15990 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15991 #}
15992 if($ExtendedCheck) {
15993 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15994 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015995 if($JoinReport)
15996 {
15997 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015998 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015999 }
16000 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016001 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016002 }
16003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016004 $TestInfo .= "</table>\n";
16005
16006 # test results
16007 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016008 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016009
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016010 if(my @Headers = keys(%{$Registered_Headers{1}}))
16011 {
16012 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16013 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16014 }
16015 elsif($CheckObjectsOnly) {
16016 $TestResults .= "<tr><th>Total Header Files</th><td>0&#160;(not&#160;analyzed)</td></tr>\n";
16017 }
16018
16019 if(my @Sources = keys(%{$Registered_Sources{1}}))
16020 {
16021 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16022 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016024
16025 if(not $ExtendedCheck)
16026 {
16027 my $Libs_Link = "0";
16028 $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 +040016029 $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 +040016030 }
16031
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016032 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016033
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016034 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016035 if($JoinReport) {
16036 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16037 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016038 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016039 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016040 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
16041 }
16042 else {
16043 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
16044 }
16045 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016046 $TestResults .= "</table>\n";
16047
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016048 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016049 # problem summary
16050 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016051 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016052 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16053
16054 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016055 if($Added>0)
16056 {
16057 if($JoinReport) {
16058 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16059 }
16060 else {
16061 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16062 }
16063 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016064 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016065 $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 +040016066
16067 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016068 if($Removed>0)
16069 {
16070 if($JoinReport) {
16071 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16072 }
16073 else {
16074 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16075 }
16076 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016077 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016078 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
16079 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016080
16081 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016082 $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 +040016083 $TH_Link = "n/a" if($CheckObjectsOnly);
16084 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016085 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
16086 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016087
16088 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016089 $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 +040016090 $TM_Link = "n/a" if($CheckObjectsOnly);
16091 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016092 $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 +040016093
16094 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016095 $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 +040016096 $TL_Link = "n/a" if($CheckObjectsOnly);
16097 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016098 $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 +040016099
16100 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016101 $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 +040016102 $IH_Link = "n/a" if($CheckObjectsOnly);
16103 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016104 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
16105 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016106
16107 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016108 $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 +040016109 $IM_Link = "n/a" if($CheckObjectsOnly);
16110 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016111 $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 +040016112
16113 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016114 $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 +040016115 $IL_Link = "n/a" if($CheckObjectsOnly);
16116 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016117 $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 +040016118
16119 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016120 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16121 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016122 }
16123 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016124 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016125 $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 +040016126
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016127 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016128 {
16129 my $ChangedImpl_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016130 $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 +040016131 $ChangedImpl_Link = "n/a" if($CheckHeadersOnly);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016132 $META_DATA .= "changed_implementation:".keys(%CompatProblems_Impl).";";
16133 $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 +040016134 }
16135 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016136 if($T_Other and not $CheckObjectsOnly)
16137 {
16138 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016139 $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 +040016140 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016141
16142 if($I_Other and not $CheckObjectsOnly)
16143 {
16144 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016145 $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 +040016146 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016147
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016148 if($C_Other and not $CheckObjectsOnly)
16149 {
16150 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16151 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
16152 }
16153
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016154 $META_DATA .= "tool_version:$TOOL_VERSION";
16155 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016156 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016157 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16158 }
16159}
16160
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016161sub getStyle($$$)
16162{
16163 my ($Subj, $Act, $Num) = @_;
16164 my %Style = (
16165 "A"=>"new",
16166 "R"=>"failed",
16167 "S"=>"passed",
16168 "L"=>"warning",
16169 "M"=>"failed",
16170 "H"=>"failed"
16171 );
16172 if($Num>0) {
16173 return " class='".$Style{$Act}."'";
16174 }
16175 return "";
16176}
16177
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016178sub show_number($)
16179{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016180 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016181 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016182 my $Num = cut_off_number($_[0], 2, 0);
16183 if($Num eq "0")
16184 {
16185 foreach my $P (3 .. 7)
16186 {
16187 $Num = cut_off_number($_[0], $P, 1);
16188 if($Num ne "0") {
16189 last;
16190 }
16191 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016192 }
16193 if($Num eq "0") {
16194 $Num = $_[0];
16195 }
16196 return $Num;
16197 }
16198 return $_[0];
16199}
16200
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016201sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016202{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016203 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016204 if($num!~/\./)
16205 {
16206 $num .= ".";
16207 foreach (1 .. $digs_to_cut-1) {
16208 $num .= "0";
16209 }
16210 }
16211 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16212 {
16213 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16214 $num .= "0";
16215 }
16216 }
16217 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16218 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16219 }
16220 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016221 if($z) {
16222 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16223 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016224 return $num;
16225}
16226
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016227sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016228{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016229 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016230 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016231
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016232 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016233 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16234 {
16235 my $Header = $Constants{1}{$Constant}{"Header"};
16236 if(not $Header)
16237 { # added
16238 $Header = $Constants{2}{$Constant}{"Header"}
16239 }
16240
16241 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16242 {
16243 if(not defined $CompatRules{$Level}{$Kind}) {
16244 next;
16245 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016246 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016247 next;
16248 }
16249 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16250 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016251 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016252
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016253 if($ReportFormat eq "xml")
16254 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016255 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016256 {
16257 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016258 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016259 {
16260 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016261 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16262 {
16263 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16264 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16265 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016266
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016267 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16268 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16269 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
16270 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16271 $CHANGED_CONSTANTS .= " </problem>\n";
16272 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016273 $CHANGED_CONSTANTS .= " </constant>\n";
16274 }
16275 $CHANGED_CONSTANTS .= " </header>\n";
16276 }
16277 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16278 }
16279 else
16280 { # HTML
16281 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016282 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016283 {
16284 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016285 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016286 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016287 my $Report = "";
16288
16289 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16290 {
16291 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16292 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16293 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16294 $Number += 1;
16295 }
16296 if($Report)
16297 {
16298 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16299 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16300 $Report = insertIDs($Report);
16301 }
16302 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016303 }
16304 $CHANGED_CONSTANTS .= "<br/>\n";
16305 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016306 if($CHANGED_CONSTANTS)
16307 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016308 my $Title = "Problems with Constants, $TargetSeverity Severity";
16309 if($TargetSeverity eq "Safe")
16310 { # Safe Changes
16311 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016312 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016313 $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 +040016314 }
16315 }
16316 return $CHANGED_CONSTANTS;
16317}
16318
16319sub get_Report_Impl()
16320{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016321 my $CHANGED_IMPLEMENTATION = "";
16322 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016323 foreach my $Interface (sort keys(%CompatProblems_Impl))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016324 {
16325 my $HeaderName = $CompleteSignature{1}{$Interface}{"Header"};
16326 my $DyLib = $Symbol_Library{1}{$Interface};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016327 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016328 }
16329 my $Changed_Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016330 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016331 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016332 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016333 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016334 my %NameSpaceSymbols = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016335 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016336 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016337 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016338 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016339 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016340 $CHANGED_IMPLEMENTATION .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016341 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016342 foreach my $Interface (@SortedInterfaces)
16343 {
16344 $Changed_Number += 1;
16345 my $Signature = get_Signature($Interface, 1);
16346 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016347 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016348 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016349 $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 +040016350 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016351 $CHANGED_IMPLEMENTATION .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016352 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016353 }
16354 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016355 if($CHANGED_IMPLEMENTATION)
16356 {
16357 $CHANGED_IMPLEMENTATION = insertIDs($CHANGED_IMPLEMENTATION);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016358 $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 +040016359 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016360
16361 # clean memory
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016362 %CompatProblems_Impl = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016363
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016364 return $CHANGED_IMPLEMENTATION;
16365}
16366
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016367sub getTitle($$$)
16368{
16369 my ($Header, $Library, $NameSpace) = @_;
16370 my $Title = "";
16371 if($Library and $Library!~/\.\w+\Z/) {
16372 $Library .= " (.$LIB_EXT)";
16373 }
16374 if($Header and $Library)
16375 {
16376 $Title .= "<span class='h_name'>$Header</span>";
16377 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16378 }
16379 elsif($Library) {
16380 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16381 }
16382 elsif($Header) {
16383 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16384 }
16385 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016386 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016387 }
16388 return $Title;
16389}
16390
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016391sub get_Report_Added($)
16392{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016393 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016394 my $ADDED_INTERFACES = "";
16395 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016396 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016397 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016398 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016399 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016400 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016401 {
16402 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16403 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016404 if($Level eq "Source" and $ReportFormat eq "html")
16405 { # do not show library name in HTML report
16406 $DyLib = "";
16407 }
16408 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016409 }
16410 }
16411 }
16412 if($ReportFormat eq "xml")
16413 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016414 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016415 {
16416 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016417 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016418 {
16419 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016420 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016421 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16422 }
16423 $ADDED_INTERFACES .= " </library>\n";
16424 }
16425 $ADDED_INTERFACES .= " </header>\n";
16426 }
16427 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16428 }
16429 else
16430 { # HTML
16431 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016432 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016433 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016434 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016435 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016436 my %NameSpaceSymbols = ();
16437 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016438 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016439 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016440 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016441 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016442 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16443 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016444 foreach my $Interface (@SortedInterfaces)
16445 {
16446 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016447 my $Signature = get_Signature($Interface, 2);
16448 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016449 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016450 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016451 if($Interface=~/\A(_Z|\?)/)
16452 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016453 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016454 $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 +040016455 }
16456 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016457 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016458 }
16459 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016460 else
16461 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016462 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016463 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016464 }
16465 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016466 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016467 }
16468 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016469 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016470 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016471 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016472 }
16473 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016474 if($ADDED_INTERFACES)
16475 {
16476 my $Anchor = "<a name='Added'></a>";
16477 if($JoinReport) {
16478 $Anchor = "<a name='".$Level."_Added'></a>";
16479 }
16480 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016481 }
16482 }
16483 return $ADDED_INTERFACES;
16484}
16485
16486sub get_Report_Removed($)
16487{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016488 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016489 my $REMOVED_INTERFACES = "";
16490 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016491 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016492 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016493 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016494 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016495 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016496 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016497 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16498 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016499 if($Level eq "Source" and $ReportFormat eq "html")
16500 { # do not show library name in HTML report
16501 $DyLib = "";
16502 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016503 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016504 }
16505 }
16506 }
16507 if($ReportFormat eq "xml")
16508 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016509 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016510 {
16511 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016512 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016513 {
16514 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016515 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16516 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016517 }
16518 $REMOVED_INTERFACES .= " </library>\n";
16519 }
16520 $REMOVED_INTERFACES .= " </header>\n";
16521 }
16522 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16523 }
16524 else
16525 { # HTML
16526 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016527 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016528 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016529 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016530 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016531 my %NameSpaceSymbols = ();
16532 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016533 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016534 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016535 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016536 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016537 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16538 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016539 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016540 {
16541 $Removed_Number += 1;
16542 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016543 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016544 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016545 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016546 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016547 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016548 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016549 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016550 $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 +040016551 }
16552 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016553 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016554 }
16555 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016556 else
16557 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016558 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016559 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016560 }
16561 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016562 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016563 }
16564 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016565 }
16566 }
16567 $REMOVED_INTERFACES .= "<br/>\n";
16568 }
16569 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016570 if($REMOVED_INTERFACES)
16571 {
16572 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16573 if($JoinReport) {
16574 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16575 }
16576 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016577 }
16578 }
16579 return $REMOVED_INTERFACES;
16580}
16581
16582sub getXmlParams($$)
16583{
16584 my ($Content, $Problem) = @_;
16585 return "" if(not $Content or not $Problem);
16586 my %XMLparams = ();
16587 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16588 {
16589 my $Macro = "\@".lc($Attr);
16590 if($Content=~/\Q$Macro\E/) {
16591 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16592 }
16593 }
16594 my @PString = ();
16595 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016596 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016597 }
16598 if(@PString) {
16599 return " ".join(" ", @PString);
16600 }
16601 else {
16602 return "";
16603 }
16604}
16605
16606sub addMarkup($)
16607{
16608 my $Content = $_[0];
16609 # auto-markup
16610 $Content=~s/\n[ ]*//; # spaces
16611 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16612 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016613 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016614 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16615 if($Content=~/\ANOTE:/)
16616 { # notes
16617 $Content=~s!(NOTE):!<b>$1</b>:!g;
16618 }
16619 else {
16620 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16621 }
16622 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16623 my @Keywords = (
16624 "void",
16625 "const",
16626 "static",
16627 "restrict",
16628 "volatile",
16629 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016630 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016631 );
16632 my $MKeys = join("|", @Keywords);
16633 foreach (@Keywords) {
16634 $MKeys .= "|non-".$_;
16635 }
16636 $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 +040016637
16638 # Markdown
16639 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16640 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016641 return $Content;
16642}
16643
16644sub applyMacroses($$$$)
16645{
16646 my ($Level, $Kind, $Content, $Problem) = @_;
16647 return "" if(not $Content or not $Problem);
16648 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16649 $Content = addMarkup($Content);
16650 # macros
16651 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16652 {
16653 my $Macro = "\@".lc($Attr);
16654 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016655 if(not defined $Value
16656 or $Value eq "") {
16657 next;
16658 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016659 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016660 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016661 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
16662 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016663 $Value = black_name($Value);
16664 }
16665 elsif($Value=~/\s/) {
16666 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16667 }
16668 elsif($Value=~/\A\d+\Z/
16669 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16670 { # bits to bytes
16671 if($Value % $BYTE_SIZE)
16672 { # bits
16673 if($Value==1) {
16674 $Value = "<b>".$Value."</b> bit";
16675 }
16676 else {
16677 $Value = "<b>".$Value."</b> bits";
16678 }
16679 }
16680 else
16681 { # bytes
16682 $Value /= $BYTE_SIZE;
16683 if($Value==1) {
16684 $Value = "<b>".$Value."</b> byte";
16685 }
16686 else {
16687 $Value = "<b>".$Value."</b> bytes";
16688 }
16689 }
16690 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016691 else
16692 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016693 $Value = "<b>".htmlSpecChars($Value)."</b>";
16694 }
16695 $Content=~s/\Q$Macro\E/$Value/g;
16696 }
16697
16698 if($Content=~/(\A|[^\@\w])\@\w/)
16699 {
16700 if(not $IncompleteRules{$Level}{$Kind})
16701 { # only one warning
16702 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16703 $IncompleteRules{$Level}{$Kind} = 1;
16704 }
16705 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016706 return $Content;
16707}
16708
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016709sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016710{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016711 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016712 my $INTERFACE_PROBLEMS = "";
16713 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016714 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016715 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016716 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16717 if($SV and defined $CompatProblems{$Level}{$SN}) {
16718 next;
16719 }
16720 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016721 {
16722 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016723 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016724 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016725 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16726 my $DyLib = $Symbol_Library{1}{$Symbol};
16727 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016728 { # Symbol with Version
16729 $DyLib = $Symbol_Library{1}{$VSym};
16730 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016731 if(not $DyLib)
16732 { # const global data
16733 $DyLib = "";
16734 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016735 if($Level eq "Source" and $ReportFormat eq "html")
16736 { # do not show library name in HTML report
16737 $DyLib = "";
16738 }
16739 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16740 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016741 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016742 my $Priority = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016743 if($Priority ne $TargetSeverity) {
16744 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016745 }
16746 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016747 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16748 {
16749 delete($SymbolChanges{$Symbol}{$Kind});
16750 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016751 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016752 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016753 }
16754 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016755 if(not keys(%{$SymbolChanges{$Symbol}})) {
16756 delete($SymbolChanges{$Symbol});
16757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016758 }
16759 if($ReportFormat eq "xml")
16760 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016761 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016762 {
16763 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016764 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016765 {
16766 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016767 foreach my $Symbol (sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%SymbolChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016768 {
16769 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16770 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16771 {
16772 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16773 {
16774 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016775 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016776
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016777 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16778 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16779 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16780 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16781 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
16782 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
16783 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16784 $INTERFACE_PROBLEMS .= " </problem>\n";
16785 }
16786 }
16787 $INTERFACE_PROBLEMS .= " </symbol>\n";
16788 }
16789 $INTERFACE_PROBLEMS .= " </library>\n";
16790 }
16791 $INTERFACE_PROBLEMS .= " </header>\n";
16792 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016793 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016794 }
16795 else
16796 { # HTML
16797 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016798 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016799 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016800 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016801 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016802 my (%NameSpaceSymbols, %NewSignature) = ();
16803 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016804 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016805 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016806 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016807 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016808 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016809 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 +040016810 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016811 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016812 my $Signature = get_Signature($Symbol, 1);
16813 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016814 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016815 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016816 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016817 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016818 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016819 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016820 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016821 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016822 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016823 }
16824 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16825 {
16826 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016827 $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 +040016828 $ProblemNum += 1;
16829 $ProblemsNum += 1;
16830 }
16831 }
16832 }
16833 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016834 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016835 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016836 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016837 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016838 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016839 }
16840 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016841 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016842 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016843 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16844 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16845 if($NewSignature{$Symbol})
16846 { # argument list changed to
16847 $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 +040016848 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016849 if($Symbol=~/\A(_Z|\?)/) {
16850 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16851 }
16852 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16853 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016854 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016855 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016856 }
16857 }
16858 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016859 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016860 }
16861 }
16862 }
16863 if($INTERFACE_PROBLEMS)
16864 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016865 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16866 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16867 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016868 { # Safe Changes
16869 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016870 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016871 $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 +040016872 }
16873 }
16874 return $INTERFACE_PROBLEMS;
16875}
16876
16877sub get_Report_TypeProblems($$)
16878{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016879 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016880 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016881 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016882 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016883 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016884 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016885 {
16886 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16887 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016888 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016889 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016890 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016891 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016892 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016893 if($Severity eq "Safe"
16894 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016895 next;
16896 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016897
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016898 if(cmpSeverities($Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target}, $Severity))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016899 { # select a problem with the highest priority
16900 next;
16901 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016902 %{$TypeChanges{$TypeName}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016903 }
16904 }
16905 }
16906 }
16907 my %Kinds_Locations = ();
16908 foreach my $TypeName (keys(%TypeChanges))
16909 {
16910 my %Kinds_Target = ();
16911 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16912 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016913 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016914 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016915 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016916 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016917 { # other priority
16918 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16919 next;
16920 }
16921 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16922 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
16923 if($Kinds_Target{$Kind}{$Target})
16924 { # duplicate target
16925 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16926 next;
16927 }
16928 $Kinds_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016929 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016930 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016931 }
16932 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16933 delete($TypeChanges{$TypeName}{$Kind});
16934 }
16935 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016936 if(not keys(%{$TypeChanges{$TypeName}})) {
16937 delete($TypeChanges{$TypeName});
16938 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016939 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016940 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 +040016941 if($ReportFormat eq "xml")
16942 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016943 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016944 {
16945 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016946 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016947 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016948 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016949 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16950 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016951 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016952 {
16953 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16954 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16955 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16956 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16957 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16958 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
16959 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
16960 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16961 $TYPE_PROBLEMS .= " </problem>\n";
16962 }
16963 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016964 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016965 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016966 $TYPE_PROBLEMS .= showVTables($TypeName);
16967 }
16968 $TYPE_PROBLEMS .= " </type>\n";
16969 }
16970 $TYPE_PROBLEMS .= " </header>\n";
16971 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016972 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016973 }
16974 else
16975 { # HTML
16976 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016977 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016978 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016979 my (%NameSpace_Type) = ();
16980 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016981 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016982 }
16983 foreach my $NameSpace (sort keys(%NameSpace_Type))
16984 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016985 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016986 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 +040016987 foreach my $TypeName (@SortedTypes)
16988 {
16989 my $ProblemNum = 1;
16990 my $TYPE_REPORT = "";
16991 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16992 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016993 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016994 {
16995 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16996 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16997 {
16998 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
16999 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
17000 $ProblemNum += 1;
17001 $ProblemsNum += 1;
17002 }
17003 }
17004 }
17005 $ProblemNum -= 1;
17006 if($TYPE_REPORT)
17007 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017008 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017009 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017010 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017011 $ShowVTables = showVTables($TypeName);
17012 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017013
17014 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017015 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17016 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17017 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17018 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017019 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017020 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017021 }
17022 }
17023 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017024 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017025 }
17026 }
17027 if($TYPE_PROBLEMS)
17028 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017029 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17030 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017031 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017032 { # Safe Changes
17033 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017034 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017035 $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 +040017036 }
17037 }
17038 return $TYPE_PROBLEMS;
17039}
17040
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017041sub show_Type($$$)
17042{
17043 my ($Name, $Html, $LibVersion) = @_;
17044 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17045 $TType = lc($TType);
17046 if($TType=~/struct|union|enum/) {
17047 $Name=~s/\A\Q$TType\E //g;
17048 }
17049 if($Html) {
17050 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17051 }
17052 else {
17053 $Name = $TType." ".$Name;
17054 }
17055 return $Name;
17056}
17057
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017058sub get_Anchor($$$)
17059{
17060 my ($Kind, $Level, $Severity) = @_;
17061 if($JoinReport)
17062 {
17063 if($Severity eq "Safe") {
17064 return "Other_".$Level."_Changes_In_".$Kind."s";
17065 }
17066 else {
17067 return $Kind."_".$Level."_Problems_".$Severity;
17068 }
17069 }
17070 else
17071 {
17072 if($Severity eq "Safe") {
17073 return "Other_Changes_In_".$Kind."s";
17074 }
17075 else {
17076 return $Kind."_Problems_".$Severity;
17077 }
17078 }
17079}
17080
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017081sub showVTables($)
17082{
17083 my $TypeName = $_[0];
17084 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017085 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017086 if(defined $Type1{"VTable"}
17087 and keys(%{$Type1{"VTable"}}))
17088 {
17089 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017090 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017091 if(defined $Type2{"VTable"}
17092 and keys(%{$Type2{"VTable"}}))
17093 {
17094 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17095 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017096 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017097 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017098 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17099 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017100 }
17101 my $VTABLES = "";
17102 if($ReportFormat eq "xml")
17103 { # XML
17104 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017105 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017106 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017107 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017108 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17109 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017110 $VTABLES .= " </entry>\n";
17111 }
17112 $VTABLES .= " </vtable>\n\n";
17113 }
17114 else
17115 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017116 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017117 $VTABLES .= "<tr><th width='2%'>Offset</th>";
17118 $VTABLES .= "<th width='45%'>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
17119 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017120 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017121 {
17122 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017123 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017124 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017125 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017126 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017127 $Color1 = " class='failed'";
17128 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017129 }
17130 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017131 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017132 }
17133 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017134 $VTABLES .= "<tr><th>".$Index."</th>\n";
17135 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17136 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017137 }
17138 $VTABLES .= "</table><br/>\n";
17139 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017140 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017141 }
17142 return $VTABLES;
17143 }
17144 }
17145 return "";
17146}
17147
17148sub simpleVEntry($)
17149{
17150 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017151 if(not defined $VEntry
17152 or $VEntry eq "") {
17153 return "";
17154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017155 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17156 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17157 if($VEntry=~/\A_ZThn.+\Z/) {
17158 $VEntry = "non-virtual thunk";
17159 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017160 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017161 # support for old GCC versions
17162 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17163 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17164 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017165 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17166 return $VEntry;
17167}
17168
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017169sub adjustParamPos($$$)
17170{
17171 my ($Pos, $Symbol, $LibVersion) = @_;
17172 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17173 {
17174 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17175 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17176 {
17177 return $Pos-1;
17178 }
17179
17180 return $Pos;
17181 }
17182
17183 return undef;
17184}
17185
17186sub getParamPos($$$)
17187{
17188 my ($Name, $Symbol, $LibVersion) = @_;
17189
17190 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17191 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17192 {
17193 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17194 foreach (keys(%{$Info->{"Param"}}))
17195 {
17196 if($Info->{"Param"}{$_}{"name"} eq $Name)
17197 {
17198 return $_;
17199 }
17200 }
17201 }
17202
17203 return undef;
17204}
17205
17206sub getParamName($)
17207{
17208 my $Loc = $_[0];
17209 $Loc=~s/\->.*//g;
17210 return $Loc;
17211}
17212
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017213sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017214{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017215 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017216 my $LIMIT = 1000;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017217
17218 if(defined $AffectLimit)
17219 {
17220 $LIMIT = $AffectLimit;
17221 }
17222 else
17223 {
17224 if($#{$Syms}>=10000)
17225 { # reduce size of the report
17226 $LIMIT = 10;
17227 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017228 }
17229 my %SProblems = ();
17230 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017231 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017232 if(keys(%SProblems)>$LIMIT) {
17233 last;
17234 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017235 if(($Symbol=~/(C2|D2|D0)[EI]/))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017236 { # duplicated problems for C2 constructors, D2 and D0 destructors
17237 next;
17238 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017239 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17240 if($Level eq "Source")
17241 { # remove symbol version
17242 $Symbol=$SN;
17243 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017244 my ($MinPath_Length, $ProblemLocation_Last) = (-1, "");
17245 my $Severity_Max = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017246 my $Signature = get_Signature($Symbol, 1);
17247 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017248 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017249 foreach my $Location (keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017250 {
17251 if(not defined $Kinds_Locations->{$Kind}
17252 or not $Kinds_Locations->{$Kind}{$Location}) {
17253 next;
17254 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017255 if($SV and defined $CompatProblems{$Level}{$SN}
17256 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Location})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017257 { # duplicated problems for versioned symbols
17258 next;
17259 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017260 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017261 next if($Type_Name ne $Target_TypeName);
17262
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017263 my $PName = getParamName($Location);
17264 my $PPos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17265
17266 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017267 my $Path_Length = 0;
17268 my $ProblemLocation = $Location;
17269 if($Type_Name) {
17270 $ProblemLocation=~s/->\Q$Type_Name\E\Z//g;
17271 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017272 while($ProblemLocation=~/\-\>/g) {
17273 $Path_Length += 1;
17274 }
17275 if($MinPath_Length==-1 or ($Path_Length<=$MinPath_Length and $Severity_Val{$Severity}>$Severity_Max)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017276 or (cmpLocations($ProblemLocation, $ProblemLocation_Last) and $Severity_Val{$Severity}==$Severity_Max))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017277 {
17278 $MinPath_Length = $Path_Length;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017279 $Severity_Max = $Severity_Val{$Severity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017280 $ProblemLocation_Last = $ProblemLocation;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017281 %{$SProblems{$Symbol}} = (
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017282 "Descr"=>getAffectDesc($Level, $Symbol, $Kind, $Location),
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017283 "Severity_Max"=>$Severity_Max,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017284 "Signature"=>$Signature,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017285 "Position"=>$PPos,
17286 "Param_Name"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017287 "Location"=>$Location
17288 );
17289 }
17290 }
17291 }
17292 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017293 my @Symbols = keys(%SProblems);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017294 @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 +040017295 @Symbols = sort {$SProblems{$b}{"Severity_Max"}<=>$SProblems{$a}{"Severity_Max"}} @Symbols;
17296 if($#Symbols+1>$LIMIT)
17297 { # remove last element
17298 pop(@Symbols);
17299 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017300 my $Affected = "";
17301 if($ReportFormat eq "xml")
17302 { # XML
17303 $Affected .= " <affected>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017304 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017305 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017306 my $Param_Name = $SProblems{$Symbol}{"Param_Name"};
17307 my $Description = $SProblems{$Symbol}{"Descr"};
17308 my $Location = $SProblems{$Symbol}{"Location"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017309 my $Target = "";
17310 if($Param_Name) {
17311 $Target = " affected=\"param\" param_name=\"$Param_Name\"";
17312 }
17313 elsif($Location=~/\Aretval(\-|\Z)/i) {
17314 $Target = " affected=\"retval\"";
17315 }
17316 elsif($Location=~/\Athis(\-|\Z)/i) {
17317 $Target = " affected=\"this\"";
17318 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017319 $Affected .= " <symbol$Target name=\"$Symbol\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017320 $Affected .= " <comment>".xmlSpecChars($Description)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017321 $Affected .= " </symbol>\n";
17322 }
17323 $Affected .= " </affected>\n";
17324 }
17325 else
17326 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017327 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017328 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017329 my $Description = $SProblems{$Symbol}{"Descr"};
17330 my $Signature = $SProblems{$Symbol}{"Signature"};
17331 my $Pos = $SProblems{$Symbol}{"Position"};
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017332 $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 +040017333 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017334 if(keys(%SProblems)>$LIMIT) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017335 $Affected .= "and others ...<br/>";
17336 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017337 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017338 if($Affected)
17339 {
17340 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017341 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".(keys(%SProblems)>$LIMIT?">".$LIMIT:keys(%SProblems)).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017342 }
17343 }
17344 return $Affected;
17345}
17346
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017347sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017348{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017349 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017350 if($L2=~/\A(retval|this)\b/
17351 and $L1!~/\A(retval|this)\b/)
17352 {
17353 if($L1!~/\-\>/) {
17354 return 1;
17355 }
17356 elsif($L2=~/\-\>/) {
17357 return 1;
17358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017359 }
17360 return 0;
17361}
17362
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017363sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017364{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017365 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017366
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017367 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017368
17369 my $Location_I = $Location;
17370 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17371
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017372 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017373
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017374 if($Kind eq "Overridden_Virtual_Method"
17375 or $Kind eq "Overridden_Virtual_Method_B") {
17376 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17377 }
17378 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17379 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017380 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17381
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017382 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17383 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017384 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17385 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17386
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017387 if($ClassName eq $Problem{"Type_Name"}) {
17388 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17389 }
17390 else {
17391 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17392 }
17393 }
17394 else
17395 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017396 my $TypeID = undef;
17397
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017398 if($Location=~/retval/)
17399 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017400 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017401 push(@Sentence, "Field \'".$Location."\' in return value");
17402 }
17403 else {
17404 push(@Sentence, "Return value");
17405 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017406
17407 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017408 }
17409 elsif($Location=~/this/)
17410 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017411 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017412 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17413 }
17414 else {
17415 push(@Sentence, "\'this\' pointer");
17416 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017417
17418 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017419 }
17420 else
17421 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017422
17423 my $PName = getParamName($Location);
17424 my $PPos = getParamPos($PName, $Symbol, 1);
17425
17426 if(index($Location, "->")!=-1) {
17427 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017428 }
17429 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017430 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017431 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017432 if($PName) {
17433 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017434 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017435
17436 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17437 }
17438
17439 if($Location!~/this/)
17440 {
17441 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017442 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017443 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017444 push(@Sentence, "(pointer)");
17445 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017446 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017447 push(@Sentence, "(reference)");
17448 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017449 }
17450 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017451
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017452 if($Location eq "this") {
17453 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17454 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017455 else
17456 {
17457 my $Location_T = $Location;
17458 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17459
17460 my $TypeID_Problem = $TypeID;
17461 if($Location_T) {
17462 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17463 }
17464
17465 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17466 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17467 }
17468 else {
17469 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17470 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017471 }
17472 }
17473 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017474 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017475 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 +040017476 }
17477 return join(" ", @Sentence);
17478}
17479
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017480sub getFieldType($$$)
17481{
17482 my ($Location, $TypeId, $LibVersion) = @_;
17483
17484 my @Fields = split("->", $Location);
17485
17486 foreach my $Name (@Fields)
17487 {
17488 my %Info = get_BaseType($TypeId, $LibVersion);
17489
17490 foreach my $Pos (keys(%{$Info{"Memb"}}))
17491 {
17492 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17493 {
17494 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17495 last;
17496 }
17497 }
17498 }
17499
17500 return $TypeId;
17501}
17502
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017503sub get_XmlSign($$)
17504{
17505 my ($Symbol, $LibVersion) = @_;
17506 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17507 my $Report = "";
17508 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17509 {
17510 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017511 my $Type = $Info->{"Param"}{$Pos}{"type"};
17512 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017513 foreach my $Typedef (keys(%ChangedTypedef))
17514 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017515 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17516 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017518 }
17519 $Report .= " <param pos=\"$Pos\">\n";
17520 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017521 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017522 $Report .= " </param>\n";
17523 }
17524 if(my $Return = $Info->{"Return"})
17525 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017526 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017527 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017528 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017529 $Report .= " </retval>\n";
17530 }
17531 return $Report;
17532}
17533
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017534sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017535{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017536 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017537 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017538 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017539 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017540 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17541 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017542 next;
17543 }
17544 $Report .= " <symbol name=\"$Symbol\">\n";
17545 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017546 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017547 {
17548 if(defined $CompleteSignature{1}{$Symbol}
17549 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17550 {
17551 $P1 = get_XmlSign($Symbol, 1);
17552 $S1 = get_Signature($Symbol, 1);
17553 }
17554 elsif($Symbol=~/\A(_Z|\?)/) {
17555 $S1 = $tr_name{$Symbol};
17556 }
17557 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017558 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017559 {
17560 if(defined $CompleteSignature{2}{$Symbol}
17561 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17562 {
17563 $P2 = get_XmlSign($Symbol, 2);
17564 $S2 = get_Signature($Symbol, 2);
17565 }
17566 elsif($Symbol=~/\A(_Z|\?)/) {
17567 $S2 = $tr_name{$Symbol};
17568 }
17569 }
17570 if($S1)
17571 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017572 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017573 $Report .= $P1;
17574 $Report .= " </old>\n";
17575 }
17576 if($S2 and $S2 ne $S1)
17577 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017578 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017579 $Report .= $P2;
17580 $Report .= " </new>\n";
17581 }
17582 $Report .= " </symbol>\n";
17583 }
17584 $Report .= "</symbols_info>\n";
17585 return $Report;
17586}
17587
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017588sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017589{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017590 my ($Level, $Report) = @_;
17591 if($ReportFormat eq "xml") {
17592 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017593 }
17594 if($StdOut)
17595 { # --stdout option
17596 print STDOUT $Report;
17597 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017598 else
17599 {
17600 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017601 mkpath(get_dirname($RPath));
17602
17603 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17604 print REPORT $Report;
17605 close(REPORT);
17606
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017607 if($Browse or $OpenReport)
17608 { # open in browser
17609 openReport($RPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017610 if($JoinReport or $DoubleReport)
17611 {
17612 if($Level eq "Binary")
17613 { # wait to open a browser
17614 sleep(1);
17615 }
17616 }
17617 }
17618 }
17619}
17620
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017621sub openReport($)
17622{
17623 my $Path = $_[0];
17624 my $Cmd = "";
17625 if($Browse)
17626 { # user-defined browser
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017627 $Cmd = $Browse." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017628 }
17629 if(not $Cmd)
17630 { # default browser
17631 if($OSgroup eq "macos") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017632 $Cmd = "open \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017633 }
17634 elsif($OSgroup eq "windows") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017635 $Cmd = "start ".path_format($Path, $OSgroup);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017636 }
17637 else
17638 { # linux, freebsd, solaris
17639 my @Browsers = (
17640 "x-www-browser",
17641 "sensible-browser",
17642 "firefox",
17643 "opera",
17644 "xdg-open",
17645 "lynx",
17646 "links"
17647 );
17648 foreach my $Br (@Browsers)
17649 {
17650 if($Br = get_CmdPath($Br))
17651 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017652 $Cmd = $Br." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017653 last;
17654 }
17655 }
17656 }
17657 }
17658 if($Cmd)
17659 {
17660 if($Debug) {
17661 printMsg("INFO", "running $Cmd");
17662 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017663 if($OSgroup ne "windows"
17664 and $OSgroup ne "macos")
17665 {
17666 if($Cmd!~/lynx|links/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017667 $Cmd .= " >\"/dev/null\" 2>&1 &";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017668 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017669 }
17670 system($Cmd);
17671 }
17672 else {
17673 printMsg("ERROR", "cannot open report in browser");
17674 }
17675}
17676
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017677sub getReport($)
17678{
17679 my $Level = $_[0];
17680 if($ReportFormat eq "xml")
17681 { # XML
17682
17683 if($Level eq "Join")
17684 {
17685 my $Report = "<reports>\n";
17686 $Report .= getReport("Binary");
17687 $Report .= getReport("Source");
17688 $Report .= "</reports>\n";
17689 return $Report;
17690 }
17691 else
17692 {
17693 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17694 my ($Summary, $MetaData) = get_Summary($Level);
17695 $Report .= $Summary."\n";
17696 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17697 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17698 $Report .= get_Report_SymbolsInfo($Level);
17699 $Report .= "</report>\n";
17700 return $Report;
17701 }
17702 }
17703 else
17704 { # HTML
17705 my $CssStyles = readModule("Styles", "Report.css");
17706 my $JScripts = readModule("Scripts", "Sections.js");
17707 if($Level eq "Join")
17708 {
17709 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17710 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017711 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
17712 my $Keywords = $TargetLibraryFName.", compatibility, API, report";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017713 my $Description = "Compatibility report for the $TargetLibraryFName $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
17714 my ($BSummary, $BMetaData) = get_Summary("Binary");
17715 my ($SSummary, $SMetaData) = get_Summary("Source");
17716 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>";
17717 $Report .= get_Report_Header("Join")."
17718 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017719 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17720 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017721 </div>";
17722 $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>";
17723 $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 +040017724 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017725 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17726 return $Report;
17727 }
17728 else
17729 {
17730 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017731 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17732 my $Keywords = $TargetLibraryFName.", ".lc($Level)." compatibility, API, report";
17733 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 +040017734 if($Level eq "Binary")
17735 {
17736 if(getArch(1) eq getArch(2)
17737 and getArch(1) ne "unknown") {
17738 $Description .= " on ".showArch(getArch(1));
17739 }
17740 }
17741 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."\n<body>\n<div><a name='Top'></a>\n";
17742 $Report .= get_Report_Header($Level)."\n".$Summary."\n";
17743 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17744 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17745 $Report .= get_SourceInfo();
17746 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017747 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017748 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17749 return $Report;
17750 }
17751 }
17752}
17753
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017754sub getLegend()
17755{
17756 return "<br/>
17757<table class='summary'>
17758<tr>
17759 <td class='new'>added</td>
17760 <td class='passed'>compatible</td>
17761</tr>
17762<tr>
17763 <td class='warning'>warning</td>
17764 <td class='failed'>incompatible</td>
17765</tr></table>\n";
17766}
17767
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017768sub createReport()
17769{
17770 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017771 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017772 writeReport("Join", getReport("Join"));
17773 }
17774 elsif($DoubleReport)
17775 { # default
17776 writeReport("Binary", getReport("Binary"));
17777 writeReport("Source", getReport("Source"));
17778 }
17779 elsif($BinaryOnly)
17780 { # --binary
17781 writeReport("Binary", getReport("Binary"));
17782 }
17783 elsif($SourceOnly)
17784 { # --source
17785 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017786 }
17787}
17788
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017789sub getReportFooter($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017790{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017791 my ($LibName, $Wide) = @_;
17792 my $FooterStyle = $Wide?"width:99%":"width:97%;padding-top:3px";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017793 my $Footer = "<div style='$FooterStyle;font-size:11px;' align='right'><i>Generated on ".(localtime time); # report date
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017794 $Footer .= " for <span style='font-weight:bold'>$LibName</span>"; # tested library/system name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017795 $Footer .= " by <a href='".$HomePage{"Wiki"}."'>ABI Compliance Checker</a>"; # tool name
17796 my $ToolSummary = "<br/>A tool for checking backward compatibility of a C/C++ library API&#160;&#160;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017797 $Footer .= " $TOOL_VERSION &#160;$ToolSummary</i></div>"; # tool version
17798 return $Footer;
17799}
17800
17801sub get_Report_Problems($$)
17802{
17803 my ($Priority, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017804 my $Report = get_Report_TypeProblems($Priority, $Level);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017805 if(my $SProblems = get_Report_SymbolProblems($Priority, $Level)) {
17806 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017808 if($Priority eq "Low")
17809 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017810 $Report .= get_Report_ChangedConstants("Low", $Level);
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +040017811 if($ReportFormat eq "html")
17812 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017813 if($CheckImpl and $Level eq "Binary") {
17814 $Report .= get_Report_Impl();
17815 }
17816 }
17817 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017818 if($Priority eq "Safe")
17819 {
17820 $Report .= get_Report_ChangedConstants("Safe", $Level);
17821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017822 if($ReportFormat eq "html")
17823 {
17824 if($Report)
17825 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017826 if($JoinReport)
17827 {
17828 if($Priority eq "Safe") {
17829 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17830 }
17831 else {
17832 $Report = "<a name=\'".$Priority."_Risk_".$Level."_Problems\'></a>".$Report;
17833 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017834 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017835 else
17836 {
17837 if($Priority eq "Safe") {
17838 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17839 }
17840 else {
17841 $Report = "<a name=\'".$Priority."_Risk_Problems\'></a>".$Report;
17842 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017843 }
17844 }
17845 }
17846 return $Report;
17847}
17848
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017849sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017850{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017851 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17852 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17853 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17854 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017855 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17856 <meta name=\"keywords\" content=\"$Keywords\" />
17857 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017858 <title>
17859 $Title
17860 </title>
17861 <style type=\"text/css\">
17862 $Styles
17863 </style>
17864 <script type=\"text/javascript\" language=\"JavaScript\">
17865 <!--
17866 $Scripts
17867 -->
17868 </script>
17869 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017870}
17871
17872sub insertIDs($)
17873{
17874 my $Text = $_[0];
17875 while($Text=~/CONTENT_ID/)
17876 {
17877 if(int($Content_Counter)%2) {
17878 $ContentID -= 1;
17879 }
17880 $Text=~s/CONTENT_ID/c_$ContentID/;
17881 $ContentID += 1;
17882 $Content_Counter += 1;
17883 }
17884 return $Text;
17885}
17886
17887sub checkPreprocessedUnit($)
17888{
17889 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017890 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017891 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017892 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017893
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017894 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017895 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017896 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017897 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017898 chomp($Line);
17899 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017900 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017901 $CurHeader = path_format($1, $OSgroup);
17902 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017903 $CurClass = "";
17904
17905 if(index($CurHeader, $TMP_DIR)==0) {
17906 next;
17907 }
17908
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017909 if(substr($CurHeaderName, 0, 1) eq "<")
17910 { # <built-in>, <command-line>, etc.
17911 $CurHeaderName = "";
17912 $CurHeader = "";
17913 }
17914
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017915 if($ExtraInfo)
17916 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017917 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017918 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17919 }
17920 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017921 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017922 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017923 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017924 if($CurHeaderName)
17925 {
17926 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17927 and not $Registered_Headers{$Version}{$CurHeader})
17928 { # not a target
17929 next;
17930 }
17931 if(not is_target_header($CurHeaderName, 1)
17932 and not is_target_header($CurHeaderName, 2))
17933 { # user-defined header
17934 next;
17935 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017936 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017937 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017938
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017939 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017940 {
17941 my ($Name, $Value) = ($1, $2);
17942 if(not $Constants{$Version}{$Name}{"Access"})
17943 {
17944 $Constants{$Version}{$Name}{"Access"} = "public";
17945 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017946 if($CurHeaderName) {
17947 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17948 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017949 }
17950 }
17951 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17952 $Constants{$Version}{$1}{"Access"} = "private";
17953 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017954 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017955 else
17956 {
17957 if(defined $ExtraDump)
17958 {
17959 if($Line=~/(\w+)\s*\(/)
17960 { # functions
17961 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17962 }
17963 #elsif($Line=~/(\w+)\s*;/)
17964 #{ # data
17965 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17966 #}
17967 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17968 $CurClass = $2;
17969 }
17970 }
17971 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017972 }
17973 close(PREPROC);
17974 foreach my $Constant (keys(%{$Constants{$Version}}))
17975 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017976 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17977 {
17978 delete($Constants{$Version}{$Constant});
17979 next;
17980 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017981 if(not $ExtraDump and ($Constant=~/_h\Z/i
17982 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017983 { # skip
17984 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017985 }
17986 else {
17987 delete($Constants{$Version}{$Constant}{"Access"});
17988 }
17989 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017990 if($Debug)
17991 {
17992 mkpath($DEBUG_PATH{$Version});
17993 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17994 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017995}
17996
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017997sub uncoverConstant($$)
17998{
17999 my ($LibVersion, $Constant) = @_;
18000 return "" if(not $LibVersion or not $Constant);
18001 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18002 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18003 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18004 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018005
18006 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018007 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018008 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18009 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018010 {
18011 push(@RecurConstant, $Constant);
18012 my $Uncovered = uncoverConstant($LibVersion, $Value);
18013 if($Uncovered ne "") {
18014 $Value = $Uncovered;
18015 }
18016 pop(@RecurConstant);
18017 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018018
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018019 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018020 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018021 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18022 }
18023 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18024}
18025
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018026sub simpleConstant($$)
18027{
18028 my ($LibVersion, $Value) = @_;
18029 if($Value=~/\W/)
18030 {
18031 my $Value_Copy = $Value;
18032 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18033 {
18034 my $Word = $1;
18035 if($Value!~/$Word\s*\(/)
18036 {
18037 my $Val = uncoverConstant($LibVersion, $Word);
18038 if($Val ne "")
18039 {
18040 $Value=~s/\b$Word\b/$Val/g;
18041 }
18042 }
18043 }
18044 }
18045 return $Value;
18046}
18047
18048sub computeValue($)
18049{
18050 my $Value = $_[0];
18051
18052 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18053 return $1;
18054 }
18055
18056 if($Value=~/\A[\d\-\+()]+\Z/) {
18057 return eval($Value);
18058 }
18059
18060 return $Value;
18061}
18062
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018063my %IgnoreConstant = map {$_=>1} (
18064 "VERSION",
18065 "VERSIONCODE",
18066 "VERNUM",
18067 "VERS_INFO",
18068 "PATCHLEVEL",
18069 "INSTALLPREFIX",
18070 "VBUILD",
18071 "VPATCH",
18072 "VMINOR",
18073 "BUILD_STRING",
18074 "BUILD_TIME",
18075 "PACKAGE_STRING",
18076 "PRODUCTION",
18077 "CONFIGURE_COMMAND",
18078 "INSTALLDIR",
18079 "BINDIR",
18080 "CONFIG_FILE_PATH",
18081 "DATADIR",
18082 "EXTENSION_DIR",
18083 "INCLUDE_PATH",
18084 "LIBDIR",
18085 "LOCALSTATEDIR",
18086 "SBINDIR",
18087 "SYSCONFDIR",
18088 "RELEASE",
18089 "SOURCE_ID",
18090 "SUBMINOR",
18091 "MINOR",
18092 "MINNOR",
18093 "MINORVERSION",
18094 "MAJOR",
18095 "MAJORVERSION",
18096 "MICRO",
18097 "MICROVERSION",
18098 "BINARY_AGE",
18099 "INTERFACE_AGE",
18100 "CORE_ABI",
18101 "PATCH",
18102 "COPYRIGHT",
18103 "TIMESTAMP",
18104 "REVISION",
18105 "PACKAGE_TAG",
18106 "PACKAGEDATE",
18107 "NUMVERSION",
18108 "Release",
18109 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018110);
18111
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018112sub constantFilter($$$)
18113{
18114 my ($Name, $Value, $Level) = @_;
18115
18116 if($Level eq "Binary")
18117 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018118 if($Name=~/_t\Z/)
18119 { # __malloc_ptr_t
18120 return 1;
18121 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018122 foreach (keys(%IgnoreConstant))
18123 {
18124 if($Name=~/(\A|_)$_(_|\Z)/)
18125 { # version
18126 return 1;
18127 }
18128 if(/\A[A-Z].*[a-z]\Z/)
18129 {
18130 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18131 { # version
18132 return 1;
18133 }
18134 }
18135 }
18136 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18137 { # version
18138 return 1;
18139 }
18140 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18141 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18142 return 1;
18143 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018144
18145 if($Value=~/\A["'].*['"]/i)
18146 { # string
18147 return 0;
18148 }
18149
18150 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18151 { # static int gcry_pth_init
18152 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018153 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018154 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018155 return 1;
18156 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018157 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018158 { # foo(p)
18159 return 1;
18160 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018161 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018162 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018163 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018164 return 1;
18165 }
18166 }
18167
18168 return 0;
18169}
18170
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018171sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018172{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018173 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018174 foreach my $Constant (keys(%{$Constants{1}}))
18175 {
18176 if($SkipConstants{1}{$Constant})
18177 { # skipped by the user
18178 next;
18179 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018180
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018181 if(my $Header = $Constants{1}{$Constant}{"Header"})
18182 {
18183 if(not is_target_header($Header, 1)
18184 and not is_target_header($Header, 2))
18185 { # user-defined header
18186 next;
18187 }
18188 }
18189 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018190 next;
18191 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018192
18193 my $Old_Value = uncoverConstant(1, $Constant);
18194
18195 if(constantFilter($Constant, $Old_Value, $Level))
18196 { # separate binary and source problems
18197 next;
18198 }
18199
18200 if(not defined $Constants{2}{$Constant}{"Value"})
18201 { # removed
18202 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18203 "Target"=>$Constant,
18204 "Old_Value"=>$Old_Value );
18205 next;
18206 }
18207
18208 if($Constants{2}{$Constant}{"Value"} eq "")
18209 { # empty value
18210 # TODO: implement a rule
18211 next;
18212 }
18213
18214 my $New_Value = uncoverConstant(2, $Constant);
18215
18216 my $Old_Value_Pure = $Old_Value;
18217 my $New_Value_Pure = $New_Value;
18218
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018219 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18220 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18221 $New_Value_Pure=~s/(\W)\s+/$1/g;
18222 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018223
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018224 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018225
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018226 if($New_Value_Pure ne $Old_Value_Pure)
18227 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018228 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18229 { # complex values
18230 next;
18231 }
18232 if(computeValue($Old_Value) eq computeValue($New_Value))
18233 { # expressions
18234 next;
18235 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018236 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18237 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18238 next;
18239 }
18240 if($Old_Value eq "0" and $New_Value eq "NULL")
18241 { # 0 => NULL
18242 next;
18243 }
18244 if($Old_Value eq "NULL" and $New_Value eq "0")
18245 { # NULL => 0
18246 next;
18247 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018248 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018249 "Target"=>$Constant,
18250 "Old_Value"=>$Old_Value,
18251 "New_Value"=>$New_Value );
18252 }
18253 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018254
18255 foreach my $Constant (keys(%{$Constants{2}}))
18256 {
18257 if(not defined $Constants{1}{$Constant}{"Value"})
18258 {
18259 if($SkipConstants{2}{$Constant})
18260 { # skipped by the user
18261 next;
18262 }
18263
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018264 if(my $Header = $Constants{2}{$Constant}{"Header"})
18265 {
18266 if(not is_target_header($Header, 1)
18267 and not is_target_header($Header, 2))
18268 { # user-defined header
18269 next;
18270 }
18271 }
18272 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018273 next;
18274 }
18275
18276 my $New_Value = uncoverConstant(2, $Constant);
18277 if(not defined $New_Value or $New_Value eq "") {
18278 next;
18279 }
18280
18281 if(constantFilter($Constant, $New_Value, $Level))
18282 { # separate binary and source problems
18283 next;
18284 }
18285
18286 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18287 "Target"=>$Constant,
18288 "New_Value"=>$New_Value );
18289 }
18290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018291}
18292
18293sub convert_integer($)
18294{
18295 my $Value = $_[0];
18296 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018297 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018298 return hex($Value);
18299 }
18300 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018301 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018302 return oct($Value);
18303 }
18304 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018305 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018306 return oct($Value);
18307 }
18308 else {
18309 return $Value;
18310 }
18311}
18312
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018313sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018314{
18315 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018316 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018317 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018318 {
18319 if($LibVersion==1)
18320 {
18321 printMsg("WARNING", "checking headers only");
18322 $CheckHeadersOnly = 1;
18323 }
18324 else {
18325 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18326 }
18327 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018328
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018329 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018330 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018331 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018332
18333 if($CheckUndefined)
18334 {
18335 my %UndefinedLibs = ();
18336
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018337 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18338
18339 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018340 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018341 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018342 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018343 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018344 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018345 if($Symbol_Library{$LibVersion}{$Symbol}
18346 or $DepSymbol_Library{$LibVersion}{$Symbol})
18347 { # exported by target library
18348 next;
18349 }
18350 if(index($Symbol, '@')!=-1)
18351 { # exported default symbol version (@@)
18352 $Symbol=~s/\@/\@\@/;
18353 if($Symbol_Library{$LibVersion}{$Symbol}
18354 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18355 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018356 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018357 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018358 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18359 $UndefinedLibs{$Path} = 1;
18360 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018361 }
18362 }
18363 }
18364 if($ExtraInfo)
18365 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018366 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018367 {
18368 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018369 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018370 foreach (@Paths)
18371 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018372 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018373 my ($Dir, $Name) = separate_path($_);
18374
18375 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018376 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018377 }
18378
18379 $Name = parse_libname($Name, "name", $OStarget);
18380 $Name=~s/\Alib//;
18381
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018382 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018383 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018384
18385 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18386 {
18387 $LibString = " -L".esc($Dir).$LibString;
18388 }
18389
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018390 writeFile($ExtraInfo."/libs-string", $LibString);
18391 }
18392 }
18393 }
18394
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018395 if($ExtraInfo) {
18396 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18397 }
18398
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018399 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018400 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018401 if($#LibPaths!=-1)
18402 {
18403 if(not keys(%{$Symbol_Library{$LibVersion}}))
18404 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018405 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018406 printMsg("WARNING", "checking headers only");
18407 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018408 }
18409 }
18410 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018411
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018412 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018413 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018414}
18415
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018416my %Prefix_Lib_Map=(
18417 # symbols for autodetecting library dependencies (by prefix)
18418 "pthread_" => ["libpthread"],
18419 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18420 "cairo_" => ["libcairo"],
18421 "gtk_" => ["libgtk-x11-2.0"],
18422 "atk_" => ["libatk-1.0"],
18423 "gdk_" => ["libgdk-x11-2.0"],
18424 "gl" => ["libGL"],
18425 "glu" => ["libGLU"],
18426 "popt" => ["libpopt"],
18427 "Py" => ["libpython"],
18428 "jpeg_" => ["libjpeg"],
18429 "BZ2_" => ["libbz2"],
18430 "Fc" => ["libfontconfig"],
18431 "Xft" => ["libXft"],
18432 "SSL_" => ["libssl"],
18433 "sem_" => ["libpthread"],
18434 "snd_" => ["libasound"],
18435 "art_" => ["libart_lgpl_2"],
18436 "dbus_g" => ["libdbus-glib-1"],
18437 "GOMP_" => ["libgomp"],
18438 "omp_" => ["libgomp"],
18439 "cms" => ["liblcms"]
18440);
18441
18442my %Pattern_Lib_Map=(
18443 "SL[a-z]" => ["libslang"]
18444);
18445
18446my %Symbol_Lib_Map=(
18447 # symbols for autodetecting library dependencies (by name)
18448 "pow" => "libm",
18449 "fmod" => "libm",
18450 "sin" => "libm",
18451 "floor" => "libm",
18452 "cos" => "libm",
18453 "dlopen" => "libdl",
18454 "deflate" => "libz",
18455 "inflate" => "libz",
18456 "move_panel" => "libpanel",
18457 "XOpenDisplay" => "libX11",
18458 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018459 "clock_gettime" => "librt",
18460 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018461);
18462
18463sub find_SymbolLibs($$)
18464{
18465 my ($LibVersion, $Symbol) = @_;
18466
18467 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18468 { # debug symbols
18469 return ();
18470 }
18471
18472 my %Paths = ();
18473
18474 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18475 {
18476 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18477 $Paths{$Path} = 1;
18478 }
18479 }
18480
18481 if(my $SymbolPrefix = getPrefix($Symbol))
18482 {
18483 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18484 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18485 }
18486
18487 if(not keys(%Paths))
18488 {
18489 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18490 {
18491 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18492 {
18493 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18494 $Paths{$Path} = 1;
18495 }
18496 }
18497 }
18498 }
18499
18500 if(not keys(%Paths))
18501 {
18502 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18503 {
18504 if($Symbol=~/\A$Prefix/)
18505 {
18506 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18507 {
18508 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18509 $Paths{$Path} = 1;
18510 }
18511 }
18512 }
18513 }
18514 }
18515
18516 if(not keys(%Paths))
18517 {
18518 if($SymbolPrefix)
18519 { # try to find a library by symbol prefix
18520 if($SymbolPrefix eq "inotify" and
18521 index($Symbol, "\@GLIBC")!=-1)
18522 {
18523 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18524 $Paths{$Path} = 1;
18525 }
18526 }
18527 else
18528 {
18529 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18530 $Paths{$Path} = 1;
18531 }
18532 }
18533 }
18534 }
18535
18536 if(my @Paths = keys(%Paths)) {
18537 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18538 }
18539 }
18540 return keys(%Paths);
18541}
18542
18543sub get_LibPath_Prefix($$)
18544{
18545 my ($LibVersion, $Prefix) = @_;
18546
18547 $Prefix = lc($Prefix);
18548 $Prefix=~s/[_]+\Z//g;
18549
18550 foreach ("-2", "2", "-1", "1", "")
18551 { # libgnome-2.so
18552 # libxml2.so
18553 # libdbus-1.so
18554 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18555 return $Path;
18556 }
18557 }
18558 return "";
18559}
18560
18561sub getPrefix($)
18562{
18563 my $Str = $_[0];
18564 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18565 { # XmuValidArea: Xmu
18566 return $1;
18567 }
18568 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18569 { # snfReadFont: snf
18570 return $1;
18571 }
18572 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18573 { # XRRTimes: XRR
18574 return $1;
18575 }
18576 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18577 { # H5HF_delete: H5
18578 return $1;
18579 }
18580 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18581 { # alarm_event_add: alarm_
18582 return $1;
18583 }
18584 elsif($Str=~/\A(([a-z])\2{1,})/i)
18585 { # ffopen
18586 return $1;
18587 }
18588 return "";
18589}
18590
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018591sub getSymbolSize($$)
18592{ # size from the shared library
18593 my ($Symbol, $LibVersion) = @_;
18594 return 0 if(not $Symbol);
18595 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18596 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18597 {
18598 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18599 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18600 {
18601 if($Size<0) {
18602 return -$Size;
18603 }
18604 }
18605 }
18606 return 0;
18607}
18608
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018609sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018610{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18611 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018612 my ($Name, $Type) = @_;
18613
18614 # single
18615 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018616 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018617 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018618 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018619 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018620
18621 # double
18622 if($Name=~/$DEFAULT_STD_PARMS/)
18623 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018624 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018625 {
18626 my ($ShortName, $FuncParams) = split_Signature($Name);
18627
18628 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18629 {
18630 if(index($FParam, "<")!=-1)
18631 {
18632 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18633 my $FParam_N = canonifyName($FParam, "T");
18634 if($FParam_N ne $FParam) {
18635 $Name=~s/\Q$FParam\E/$FParam_N/g;
18636 }
18637 }
18638 }
18639 }
18640 elsif($Type eq "T")
18641 {
18642 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18643
18644 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018645 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018646 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018647 my $FParam = $TParams[0];
18648 foreach my $Pos (1 .. $#TParams)
18649 {
18650 my $TParam = $TParams[$Pos];
18651 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18652 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18653 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018654 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018655 }
18656 }
18657 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018658 if($Type eq "S") {
18659 return formatName($Name, "S");
18660 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018661 return $Name;
18662}
18663
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018664sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018665{
18666 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018667 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018668 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018669 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018670 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018671 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018672 next if($tr_name{$Symbol});
18673 $Symbol=~s/[\@\$]+(.*)\Z//;
18674 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018675 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018676 elsif(index($Symbol, "?")==0)
18677 {
18678 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018679 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018680 }
18681 else
18682 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018683 $tr_name{$Symbol} = $Symbol;
18684 $mangled_name_gcc{$Symbol} = $Symbol;
18685 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018686 }
18687 }
18688 if($#MnglNames1 > -1)
18689 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018690 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018691 foreach my $MnglName (@MnglNames1)
18692 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018693 if(my $Unmangled = pop(@UnmangledNames))
18694 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018695 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018696 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18697 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18698 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018699 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018700 and $tr_name{$MnglName}=~/vtable for (.+)/)
18701 { # bind class name and v-table symbol
18702 my $ClassName = $1;
18703 $ClassVTable{$ClassName} = $MnglName;
18704 $VTableClass{$MnglName} = $ClassName;
18705 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018706 }
18707 }
18708 }
18709 if($#MnglNames2 > -1)
18710 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018711 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018712 foreach my $MnglName (@MnglNames2)
18713 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018714 if(my $Unmangled = pop(@UnmangledNames))
18715 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018716 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018717 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18718 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018719 }
18720 }
18721 return \%tr_name;
18722}
18723
18724sub link_symbol($$$)
18725{
18726 my ($Symbol, $RunWith, $Deps) = @_;
18727 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18728 return 1;
18729 }
18730 if($Deps eq "+Deps")
18731 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018732 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018733 return 1;
18734 }
18735 }
18736 return 0;
18737}
18738
18739sub link_symbol_internal($$$)
18740{
18741 my ($Symbol, $RunWith, $Where) = @_;
18742 return 0 if(not $Where or not $Symbol);
18743 if($Where->{$RunWith}{$Symbol})
18744 { # the exact match by symbol name
18745 return 1;
18746 }
18747 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18748 { # indirect symbol version, i.e.
18749 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018750 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018751 if($Where->{$RunWith}{$VSym}) {
18752 return 1;
18753 }
18754 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018755 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018756 if($Sym and $Ver)
18757 { # search for the symbol with the same version
18758 # or without version
18759 if($Where->{$RunWith}{$Sym})
18760 { # old: foo@v|foo@@v
18761 # new: foo
18762 return 1;
18763 }
18764 if($Where->{$RunWith}{$Sym."\@".$Ver})
18765 { # old: foo|foo@@v
18766 # new: foo@v
18767 return 1;
18768 }
18769 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18770 { # old: foo|foo@v
18771 # new: foo@@v
18772 return 1;
18773 }
18774 }
18775 return 0;
18776}
18777
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018778sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018779{
18780 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018781 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018782 my @Imported = ();
18783 if($OSgroup eq "macos")
18784 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018785 my $NM = get_CmdPath("nm");
18786 if(not $NM) {
18787 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018788 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018789 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018790 while(<APP>)
18791 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018792 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018793 push(@Imported, $1);
18794 }
18795 }
18796 close(APP);
18797 }
18798 elsif($OSgroup eq "windows")
18799 {
18800 my $DumpBinCmd = get_CmdPath("dumpbin");
18801 if(not $DumpBinCmd) {
18802 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18803 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018804 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018805 while(<APP>)
18806 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018807 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18808 push(@Imported, $1);
18809 }
18810 }
18811 close(APP);
18812 }
18813 else
18814 {
18815 my $ReadelfCmd = get_CmdPath("readelf");
18816 if(not $ReadelfCmd) {
18817 exitStatus("Not_Found", "can't find \"readelf\"");
18818 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018819 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018820 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018821 while(<APP>)
18822 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018823 if(defined $symtab)
18824 { # do nothing with symtab
18825 if(index($_, "'.dynsym'")!=-1)
18826 { # dynamic table
18827 $symtab = undef;
18828 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018829 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018830 elsif(index($_, "'.symtab'")!=-1)
18831 { # symbol table
18832 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018833 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018834 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018835 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018836 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18837 if($Ndx eq "UND")
18838 { # only imported symbols
18839 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018840 }
18841 }
18842 }
18843 close(APP);
18844 }
18845 return @Imported;
18846}
18847
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018848my %ELF_BIND = map {$_=>1} (
18849 "WEAK",
18850 "GLOBAL"
18851);
18852
18853my %ELF_TYPE = map {$_=>1} (
18854 "FUNC",
18855 "IFUNC",
18856 "OBJECT",
18857 "COMMON"
18858);
18859
18860my %ELF_VIS = map {$_=>1} (
18861 "DEFAULT",
18862 "PROTECTED"
18863);
18864
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018865sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018866{ # read the line of 'readelf' output corresponding to the symbol
18867 my @Info = split(/\s+/, $_[0]);
18868 # Num: Value Size Type Bind Vis Ndx Name
18869 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018870 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018871 shift(@Info); # spaces
18872 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018873
18874 if($#Info==7)
18875 { # UND SYMBOL (N)
18876 if($Info[7]=~/\(\d+\)/) {
18877 pop(@Info);
18878 }
18879 }
18880
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018881 if($#Info!=6)
18882 { # other lines
18883 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018884 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018885 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018886 return () if(not defined $ELF_BIND{$Info[3]});
18887 return () if(not defined $ELF_VIS{$Info[4]});
18888 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18889 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18890 return ();
18891 }
18892 if($OStarget eq "symbian")
18893 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18894 if(index($Info[6], "_._.absent_export_")!=-1)
18895 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18896 return ();
18897 }
18898 $Info[6]=~s/\@.+//g; # remove version
18899 }
18900 if(index($Info[2], "0x") == 0)
18901 { # size == 0x3d158
18902 $Info[2] = hex($Info[2]);
18903 }
18904 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018905}
18906
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018907sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018908{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018909 my ($LibVersion, $Name) = @_;
18910 return "" if(not $LibVersion or not $Name);
18911 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18912 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018913 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018914 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18915}
18916
18917sub get_LibPath_I($$)
18918{
18919 my ($LibVersion, $Name) = @_;
18920 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018921 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018922 if(-f $Name)
18923 { # absolute path
18924 return $Name;
18925 }
18926 else
18927 { # broken
18928 return "";
18929 }
18930 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018931 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018932 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018933 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018934 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018935 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018936 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018937 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018938 }
18939 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18940 { # ldconfig default paths
18941 return $DefaultPath;
18942 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018943 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018944 { # search in default linker directories
18945 # and then in all system paths
18946 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018947 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018948 }
18949 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018950 if(not defined $Cache{"checkSystemFiles"}) {
18951 checkSystemFiles();
18952 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018953 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18954 return $AllObjects[0];
18955 }
18956 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18957 {
18958 if($ShortName ne $Name)
18959 { # FIXME: check this case
18960 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18961 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018962 }
18963 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018964 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018965 # can't find
18966 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018967}
18968
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018969sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018970{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018971 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18972 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018973
18974 my $Real_Path = realpath($Lib_Path);
18975
18976 if(not $Real_Path)
18977 { # broken link
18978 return ();
18979 }
18980
18981 my $Lib_Name = get_filename($Real_Path);
18982
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018983 if($ExtraInfo)
18984 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018985 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018986 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018987 }
18988
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018989 if($IsNeededLib)
18990 {
18991 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18992 return ();
18993 }
18994 }
18995 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018996 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018997
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018998 if($CheckImpl)
18999 {
19000 if(not $IsNeededLib) {
19001 getImplementations($LibVersion, $Lib_Path);
19002 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019003 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019004
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019005 push(@RecurLib, $Lib_Name);
19006 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019007 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19008
19009 if(not $IsNeededLib)
19010 { # special cases: libstdc++ and libc
19011 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19012 {
19013 if($ShortName eq "libstdc++")
19014 { # libstdc++.so.6
19015 $STDCXX_TESTING = 1;
19016 }
19017 elsif($ShortName eq "libc")
19018 { # libc-2.11.3.so
19019 $GLIBC_TESTING = 1;
19020 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019021 }
19022 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019023 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019024 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019025 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019026 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019027 mkpath(get_dirname($DebugPath));
19028 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019029 if($OStarget eq "macos")
19030 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019031 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019032 if(not $NM) {
19033 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019034 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019035 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019036 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019037 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019038 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019039 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019040 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019041 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019042 else
19043 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019044 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019046 while(<LIB>)
19047 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019048 if($CheckUndefined)
19049 {
19050 if(not $IsNeededLib)
19051 {
19052 if(/ U _([\w\$]+)\s*\Z/)
19053 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019054 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019055 next;
19056 }
19057 }
19058 }
19059
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019060 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019061 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019062 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019063 if($IsNeededLib)
19064 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019065 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019066 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019067 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19068 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019069 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019070 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019071 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019072 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019073 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19074 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019075 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19076 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019077 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019078 setLanguage($LibVersion, "C++");
19079 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019080 }
19081 if($CheckObjectsOnly
19082 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019083 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019084 }
19085 }
19086 }
19087 }
19088 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019089
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019090 if($Deps)
19091 {
19092 if($LIB_TYPE eq "dynamic")
19093 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019094
19095 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019096 if(not $OtoolCmd) {
19097 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019098 }
19099
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019100 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19101 while(<LIB>)
19102 {
19103 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19104 and $1 ne $Lib_Path) {
19105 $NeededLib{$1} = 1;
19106 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019107 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019108 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019109 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019110 }
19111 }
19112 elsif($OStarget eq "windows")
19113 { # Windows *.dll, *.lib
19114 my $DumpBinCmd = get_CmdPath("dumpbin");
19115 if(not $DumpBinCmd) {
19116 exitStatus("Not_Found", "can't find \"dumpbin\"");
19117 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019118 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019119 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019120 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019121 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019122 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019123 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019124 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019125 else
19126 { # write to pipe
19127 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019128 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019129 while(<LIB>)
19130 { # 1197 4AC 0000A620 SetThreadStackGuarantee
19131 # 1198 4AD SetThreadToken (forwarded to ...)
19132 # 3368 _o2i_ECPublicKey
19133 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*\Z/i
19134 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
19135 or /\A\s*\d+\s+_([\w\?\@]+)\s*\Z/)
19136 { # dynamic, static and forwarded symbols
19137 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019138 if($IsNeededLib)
19139 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019140 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019141 {
19142 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19143 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19144 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019145 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019146 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019147 {
19148 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19149 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019150 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19151 {
19152 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19153 setLanguage($LibVersion, "C++");
19154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019155 }
19156 if($CheckObjectsOnly
19157 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019158 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019159 }
19160 }
19161 }
19162 }
19163 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019164
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019165 if($Deps)
19166 {
19167 if($LIB_TYPE eq "dynamic")
19168 { # dependencies
19169 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19170 while(<LIB>)
19171 {
19172 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19173 and $1 ne $Lib_Path) {
19174 $NeededLib{path_format($1, $OSgroup)} = 1;
19175 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019176 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019177 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019178 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019179 }
19180 }
19181 else
19182 { # Unix; *.so, *.a
19183 # Symbian: *.dso, *.lib
19184 my $ReadelfCmd = get_CmdPath("readelf");
19185 if(not $ReadelfCmd) {
19186 exitStatus("Not_Found", "can't find \"readelf\"");
19187 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019188 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019189 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019190 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019191 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019192 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019193 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019194 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019195 else
19196 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019197 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019198 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019199 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019200 while(<LIB>)
19201 {
19202 if($LIB_TYPE eq "dynamic")
19203 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019204 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019205 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019206 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019207 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019208 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019209 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019210 # do nothing with symtab
19211 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019212 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019213 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019214 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019215 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019216 next;
19217 }
19218 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019219 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019220 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019221 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019222 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019223 if($CheckUndefined)
19224 {
19225 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019226 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019227 }
19228 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019229 next;
19230 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019231 if($Bind eq "WEAK")
19232 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019233 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019234 if($Weak eq "-Weak")
19235 { # skip WEAK symbols
19236 next;
19237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019238 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019239 my $Short = $Symbol;
19240 $Short=~s/\@.+//g;
19241 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019242 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019243 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19244 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019245 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019246 if($IsNeededLib)
19247 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019248 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019249 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019250 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19251 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019253 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019254 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019255 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019256 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19257 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19258 if($Vers)
19259 {
19260 if($LIB_EXT eq "so")
19261 { # value
19262 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19263 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19264 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019265 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019266 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19267 {
19268 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19269 setLanguage($LibVersion, "C++");
19270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019271 }
19272 if($CheckObjectsOnly
19273 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019274 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019275 }
19276 }
19277 }
19278 }
19279 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019280
19281 if($Deps and $LIB_TYPE eq "dynamic")
19282 { # dynamic library specifics
19283 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19284 open(LIB, $Cmd." |");
19285
19286 while(<LIB>)
19287 {
19288 if(/NEEDED.+\[([^\[\]]+)\]/)
19289 { # dependencies:
19290 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19291 $NeededLib{$1} = 1;
19292 }
19293 }
19294
19295 close(LIB);
19296 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019297 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019298 if($Vers)
19299 {
19300 if(not $IsNeededLib and $LIB_EXT eq "so")
19301 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019302 my %Found = ();
19303
19304 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019305 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019306 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019307 next if(index($Symbol,"\@")==-1);
19308 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019309 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019310 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019311 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019312 if($Symbol_SameValue ne $Symbol
19313 and index($Symbol_SameValue,"\@")==-1)
19314 {
19315 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019316 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019317 last;
19318 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019319 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019320 }
19321 }
19322
19323 # default
19324 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19325 {
19326 next if(defined $Found{$Symbol});
19327 next if(index($Symbol,"\@\@")==-1);
19328
19329 if($Symbol=~/\A([^\@]*)\@\@/
19330 and not $SymVer{$LibVersion}{$1})
19331 {
19332 $SymVer{$LibVersion}{$1} = $Symbol;
19333 $Found{$Symbol} = 1;
19334 }
19335 }
19336
19337 # non-default
19338 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19339 {
19340 next if(defined $Found{$Symbol});
19341 next if(index($Symbol,"\@")==-1);
19342
19343 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19344 and not $SymVer{$LibVersion}{$1})
19345 {
19346 $SymVer{$LibVersion}{$1} = $Symbol;
19347 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019348 }
19349 }
19350 }
19351 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019352 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019353 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019354 foreach my $DyLib (sort keys(%NeededLib))
19355 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019356 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19357
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019358 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19359 {
19360 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19361 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19362 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019363 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019364 }
19365 }
19366 pop(@RecurLib);
19367 return $Library_Symbol{$LibVersion};
19368}
19369
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019370sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019371{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019372 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019373 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019374 return keys(%Prefixes);
19375}
19376
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019377sub get_prefixes_I($$)
19378{
19379 foreach my $P (@{$_[0]})
19380 {
19381 my @Parts = reverse(split(/[\/\\]+/, $P));
19382 my $Name = $Parts[0];
19383 foreach (1 .. $#Parts)
19384 {
19385 $_[1]->{$Name}{$P} = 1;
19386 last if($_>4 or $Parts[$_] eq "include");
19387 $Name = $Parts[$_].$SLASH.$Name;
19388 }
19389 }
19390}
19391
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019392sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019393{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019394 $Cache{"checkSystemFiles"} = 1;
19395
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019396 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019397
19398 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019399 {
19400 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019401
19402 my @Files = cmd_find($DevelPath);
19403
19404 if(not $CheckObjectsOnly)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019405 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019406 # search for headers in /usr/lib
Andrey Ponomarenko13bb0332013-06-28 15:32:28 +040019407 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19408 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19409 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019410 }
19411
19412 # search for libraries in /usr/lib (including symbolic links)
19413 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19414 foreach my $Path (@Libs)
19415 {
19416 my $N = get_filename($Path);
19417 $SystemObjects{$N}{$Path} = 1;
19418 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019419 }
19420 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019421
19422 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019423 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019424 foreach my $DevelPath (@{$SystemPaths{"include"}})
19425 {
19426 next if(not -d $DevelPath);
19427 # search for all header files in the /usr/include
19428 # with or without extension (ncurses.h, QtCore, ...)
19429 push(@SysHeaders, cmd_find($DevelPath,"f"));
19430 foreach my $Link (cmd_find($DevelPath,"l"))
19431 { # add symbolic links
19432 if(-f $Link) {
19433 push(@SysHeaders, $Link);
19434 }
19435 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019436 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019437 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019438 }
19439}
19440
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019441sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019442{
19443 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019444 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019445 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19446 {
19447 if(not -e $Dest) {
19448 exitStatus("Access_Error", "can't access \'$Dest\'");
19449 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019450 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019451 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19452 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019453 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019454 }
19455 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019456 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019457}
19458
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019459sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019460{
19461 my ($Path, $LibVersion) = @_;
19462 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019463 my $Name = get_filename($Path);
19464 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019465 return 1;
19466 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019467 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019468 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19469 return 1;
19470 }
19471 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19472 {
19473 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19474 return 1;
19475 }
19476 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019477 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019478 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019479 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019480 return 1;
19481 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019482 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019483 return 1;
19484 }
19485 }
19486 return 0;
19487}
19488
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019489sub specificHeader($$)
19490{
19491 my ($Header, $Spec) = @_;
19492 my $Name = get_filename($Header);
19493
19494 if($Spec eq "windows")
19495 {# MS Windows
19496 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19497 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19498 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19499 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19500 my @Dirs = (
19501 "win32",
19502 "win64",
19503 "win",
19504 "windows",
19505 "msvcrt"
19506 ); # /gsf-win32/
19507 if(my $DIRs = join("|", @Dirs)) {
19508 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19509 }
19510 }
19511 elsif($Spec eq "macos")
19512 { # Mac OS
19513 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19514 }
19515
19516 return 0;
19517}
19518
19519sub skipAlienHeader($)
19520{
19521 my $Path = $_[0];
19522 my $Name = get_filename($Path);
19523 my $Dir = get_dirname($Path);
19524
19525 if($Tolerance=~/2/)
19526 { # 2 - skip internal headers
19527 my @Terms = (
19528 "p",
19529 "priv",
19530 "int",
19531 "impl",
19532 "implementation",
19533 "internal",
19534 "private",
19535 "old",
19536 "compat",
19537 "debug",
19538 "test",
19539 "gen"
19540 );
19541
19542 my @Dirs = (
19543 "private",
19544 "priv",
19545 "port",
19546 "impl",
19547 "internal",
19548 "detail",
19549 "details",
19550 "old",
19551 "compat",
19552 "debug",
19553 "config",
19554 "compiler",
19555 "platform",
19556 "test"
19557 );
19558
19559 if(my $TERMs = join("|", @Terms)) {
19560 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19561 }
19562 if(my $DIRs = join("|", @Dirs)) {
19563 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19564 }
19565
19566 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19567 }
19568
19569 if($Tolerance=~/1/)
19570 { # 1 - skip non-Linux headers
19571 if($OSgroup ne "windows")
19572 {
19573 if(specificHeader($Path, "windows")) {
19574 return 1;
19575 }
19576 }
19577 if($OSgroup ne "macos")
19578 {
19579 if(specificHeader($Path, "macos")) {
19580 return 1;
19581 }
19582 }
19583 }
19584
19585 # valid
19586 return 0;
19587}
19588
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019589sub skipHeader($$)
19590{
19591 my ($Path, $LibVersion) = @_;
19592 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019593 if(defined $Cache{"skipHeader"}{$Path}) {
19594 return $Cache{"skipHeader"}{$Path};
19595 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019596 if(defined $Tolerance and $Tolerance=~/1|2/)
19597 { # --tolerant
19598 if(skipAlienHeader($Path)) {
19599 return ($Cache{"skipHeader"}{$Path} = 1);
19600 }
19601 }
19602 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19603 return 0;
19604 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019605 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19606}
19607
19608sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019609{ # returns:
19610 # 1 - if header should NOT be included and checked
19611 # 2 - if header should NOT be included, but should be checked
19612 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019613 my $Name = get_filename($Path);
19614 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019615 return $Kind;
19616 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019617 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19618 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019619 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019620 if(index($Path, $D)!=-1)
19621 {
19622 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19623 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19624 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019625 }
19626 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019627 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19628 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019629 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019630 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19631 {
19632 if($Name=~/$P/) {
19633 return $Kind;
19634 }
19635 if($P=~/[\/\\]/ and $Path=~/$P/) {
19636 return $Kind;
19637 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019638 }
19639 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019640
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019641 return 0;
19642}
19643
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019644sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019645{
19646 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019647 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019648 { # system directory
19649 return;
19650 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019651 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019652 { # already registered
19653 return;
19654 }
19655 foreach my $Path (find_libs($Dir,"",1))
19656 {
19657 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019658 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019659 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019660 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019661 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19662}
19663
19664sub registerObject($$)
19665{
19666 my ($Path, $LibVersion) = @_;
19667 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019668 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019669 if($OSgroup=~/linux|bsd/i)
19670 {
19671 if(my $SONAME = getSONAME($Path)) {
19672 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19673 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019674 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019675 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19676 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019677 }
19678}
19679
19680sub getSONAME($)
19681{
19682 my $Path = $_[0];
19683 return if(not $Path);
19684 if(defined $Cache{"getSONAME"}{$Path}) {
19685 return $Cache{"getSONAME"}{$Path};
19686 }
19687 my $ObjdumpCmd = get_CmdPath("objdump");
19688 if(not $ObjdumpCmd) {
19689 exitStatus("Not_Found", "can't find \"objdump\"");
19690 }
19691 my $SonameCmd = "$ObjdumpCmd -x $Path 2>$TMP_DIR/null";
19692 if($OSgroup eq "windows") {
19693 $SonameCmd .= " | find \"SONAME\"";
19694 }
19695 else {
19696 $SonameCmd .= " | grep SONAME";
19697 }
19698 if(my $SonameInfo = `$SonameCmd`) {
19699 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19700 return ($Cache{"getSONAME"}{$Path} = $1);
19701 }
19702 }
19703 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019704}
19705
19706sub getSOPaths_Dest($$)
19707{
19708 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019709 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019710 return ();
19711 }
19712 if(-f $Dest)
19713 {
19714 if(not parse_libname($Dest, "name", $OStarget)) {
19715 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19716 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019717 registerObject($Dest, $LibVersion);
19718 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019719 return ($Dest);
19720 }
19721 elsif(-d $Dest)
19722 {
19723 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019724 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019725 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019726 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19727 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019728 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019729 { # all files and symlinks that match the name of a library
19730 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19731 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019732 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019733 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019734 }
19735 }
19736 }
19737 else
19738 { # search for all files and symlinks
19739 foreach my $Path (find_libs($Dest,"",""))
19740 {
19741 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019742 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019743 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019744 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019745 }
19746 if($OSgroup eq "macos")
19747 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019748 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019749 {
19750 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019751 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019752 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019753 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19754 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019755 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019756 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019757 }
19758 }
19759 }
19760 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019761 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019762 }
19763 else {
19764 return ();
19765 }
19766}
19767
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019768sub isCyclical($$)
19769{
19770 my ($Stack, $Value) = @_;
19771 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019772}
19773
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019774sub detectWordSize()
19775{
19776 return "" if(not $GCC_PATH);
19777 if($Cache{"detectWordSize"}) {
19778 return $Cache{"detectWordSize"};
19779 }
19780 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019781 my $Defines = `$GCC_PATH -E -dD \"$TMP_DIR/empty.h\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019782 unlink("$TMP_DIR/empty.h");
19783 my $WSize = 0;
19784 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019785 { # GCC 4
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019786 $WSize = $1;
19787 }
19788 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019789 { # GCC 3
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019790 my $PTRDIFF = $1;
19791 if($PTRDIFF=~/long/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019792 $WSize = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019793 }
19794 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019795 $WSize = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019796 }
19797 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019798 if(not $WSize) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019799 exitStatus("Error", "can't check WORD size");
19800 }
19801 return ($Cache{"detectWordSize"} = $WSize);
19802}
19803
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019804sub getWordSize($) {
19805 return $WORD_SIZE{$_[0]};
19806}
19807
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019808sub majorVersion($)
19809{
19810 my $V = $_[0];
19811 return 0 if(not $V);
19812 my @VParts = split(/\./, $V);
19813 return $VParts[0];
19814}
19815
19816sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019817{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019818 my ($V1, $V2) = @_;
19819 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019820 my @V1Parts = split(/\./, $V1);
19821 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019822 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19823 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019824 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19825 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19826 }
19827 return -1 if($#V1Parts < $#V2Parts);
19828 return 1 if($#V1Parts > $#V2Parts);
19829 return 0;
19830}
19831
19832sub read_ABI_Dump($$)
19833{
19834 my ($LibVersion, $Path) = @_;
19835 return if(not $LibVersion or not -e $Path);
19836 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019837 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019838 { # input *.abi
19839 $FilePath = $Path;
19840 }
19841 else
19842 { # input *.abi.tar.gz
19843 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019844 if(not isDump_U($FilePath)) {
19845 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19846 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019847 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019848
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019849 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019850
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019851 my $Line = readLineNum($FilePath, 0);
19852 if($Line=~/xml/)
19853 { # XML format
19854 loadModule("XmlDump");
19855 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019856 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019857 else
19858 { # Perl Data::Dumper format (default)
19859 open(DUMP, $FilePath);
19860 local $/ = undef;
19861 my $Content = <DUMP>;
19862 close(DUMP);
19863
19864 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19865 { # remove temp file
19866 unlink($FilePath);
19867 }
19868 if($Content!~/};\s*\Z/) {
19869 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19870 }
19871 $ABI = eval($Content);
19872 if(not $ABI) {
19873 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19874 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019875 }
19876 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019877 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019878 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019879 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019880 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019881 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019882 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019883 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019884
19885 if($ABI->{"ABI_DUMP_VERSION"})
19886 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019887 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019888 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019889 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019890 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019891 }
19892 else
19893 { # support for old ABI dumps
19894 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019895 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019896 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019897 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019898 }
19899 if(majorVersion($DVersion)<2)
19900 { # support for old ABI dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019901 if($UseOldDumps)
19902 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019903 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
19904 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019905 }
19906 }
19907 else
19908 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019909 my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019910 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019911 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019912 }
19913 exitStatus("Dump_Version", $Msg);
19914 }
19915 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019916
19917 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19918 { # DWARF ABI Dump
19919 $UseConv_Real{$LibVersion}{"P"} = 1;
19920 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19921
19922 $UsedDump{$LibVersion}{"DWARF"} = 1;
19923
19924 $TargetComponent = "module";
19925 }
19926
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019927 if(not checkDump($LibVersion, "2.11"))
19928 { # old ABI dumps
19929 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019930 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019931 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019932 { # ABI dump created with --binary option
19933 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19934 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019935 else
19936 { # default
19937 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19938 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019939
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019940 if(defined $ABI->{"Mode"}
19941 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019942 { # --ext option
19943 $ExtendedCheck = 1;
19944 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019945 if($ABI->{"Extra"}) {
19946 $ExtraDump = 1;
19947 }
19948
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019949 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019950 {
19951 $UsedDump{$LibVersion}{"L"} = $Lang;
19952 setLanguage($LibVersion, $Lang);
19953 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019954 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019955 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019956 }
19957 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019958 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019959 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019960 if(not $TInfo)
19961 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019962 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019963 }
19964 my %Tid_TDid = ();
19965 foreach my $TDid (keys(%{$TInfo}))
19966 {
19967 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19968 {
19969 $MAX_ID = $Tid if($Tid>$MAX_ID);
19970 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019971 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019972 }
19973 }
19974 my %NewID = ();
19975 foreach my $Tid (keys(%Tid_TDid))
19976 {
19977 my @TDids = keys(%{$Tid_TDid{$Tid}});
19978 if($#TDids>=1)
19979 {
19980 foreach my $TDid (@TDids)
19981 {
19982 if($TDid) {
19983 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19984 }
19985 else
19986 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019987 my $ID = ++$MAX_ID;
19988
19989 $NewID{$TDid}{$Tid} = $ID;
19990 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19991 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019992 }
19993 }
19994 }
19995 else
19996 {
19997 my $TDid = $TDids[0];
19998 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19999 }
20000 }
20001 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20002 {
20003 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20004 if(defined $Info{"BaseType"})
20005 {
20006 my $Bid = $Info{"BaseType"}{"Tid"};
20007 my $BDid = $Info{"BaseType"}{"TDid"};
20008 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020009 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020010 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20011 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20012 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020013 }
20014 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20015 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020016 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020017 read_Machine_DumpInfo($ABI, $LibVersion);
20018 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020019 if(not $SymbolInfo{$LibVersion})
20020 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020021 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020022 }
20023 if(not keys(%{$SymbolInfo{$LibVersion}}))
20024 { # validation of old-version dumps
20025 if(not $ExtendedCheck) {
20026 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20027 }
20028 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020029 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020030 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020031 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020032 else
20033 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020034 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020035 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020036 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020037 }
20038 if(not $DepSymbols)
20039 { # Cannot reconstruct DepSymbols. This may result in false
20040 # positives if the old dump is for library 2. Not a problem if
20041 # old dumps are only from old libraries.
20042 $DepSymbols = {};
20043 }
20044 foreach my $Symbol (keys(%{$DepSymbols})) {
20045 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20046 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020047 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020048 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
20049 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20050 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020051 if(not $SkipTypes{$LibVersion})
20052 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020053 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020054 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020055 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020056 if(not $SkipSymbols{$LibVersion})
20057 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020058 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020059 }
20060 if(not $SkipSymbols{$LibVersion})
20061 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020062 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020063 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020064 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
20065 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20066 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020067 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020068 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020069 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020070 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020071 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020072 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020073 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020074 if(not checkDump($LibVersion, "2.10.1")
20075 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020076 { # support for old ABI dumps: added target headers
20077 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020078 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020079 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020080 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020081 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020082 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020083 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020084 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020085 if(defined $ABI->{"GccConstants"})
20086 { # 3.0
20087 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20088 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20089 }
20090 }
20091
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020092 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020093 if(not $NestedNameSpaces{$LibVersion})
20094 { # support for old dumps
20095 # Cannot reconstruct NameSpaces. This may affect design
20096 # of the compatibility report.
20097 $NestedNameSpaces{$LibVersion} = {};
20098 }
20099 # target system type
20100 # needed to adopt HTML report
20101 if(not $DumpSystem)
20102 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020103 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020104 }
20105 # recreate environment
20106 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20107 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020108 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020109 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020110 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20111 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020112 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020113 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020114 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020115 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20116 {
20117 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20118 setLanguage($LibVersion, "C++");
20119 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020120 }
20121 }
20122 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020123 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20124 {
20125 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20126 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20127 }
20128 }
20129
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020130 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020131 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020132 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020133 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020134 {
20135 if(not $Symbol_Library{$LibVersion}{$MnglName}
20136 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20137 push(@VFunc, $MnglName);
20138 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020139 }
20140 }
20141 translateSymbols(@VFunc, $LibVersion);
20142 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020143 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20144
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020145 if(not checkDump($LibVersion, "3.0"))
20146 { # support for old ABI dumps
20147 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20148 {
20149 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20150 {
20151 if(ref($BaseType) eq "HASH") {
20152 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20153 }
20154 }
20155 }
20156 }
20157
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020158 if(not checkDump($LibVersion, "3.2"))
20159 { # support for old ABI dumps
20160 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20161 {
20162 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20163 {
20164 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20165 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20166 }
20167 }
20168 }
20169
20170 # repair target headers list
20171 delete($TargetHeaders{$LibVersion});
20172 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020173 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20174 }
20175 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20176 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020177 }
20178
20179 # non-target constants from anon enums
20180 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20181 {
20182 if(not $ExtraDump
20183 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20184 {
20185 delete($Constants{$LibVersion}{$Name});
20186 }
20187 }
20188 }
20189
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020190 if(not checkDump($LibVersion, "2.20"))
20191 { # support for old ABI dumps
20192 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20193 {
20194 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20195
20196 if($TType=~/Struct|Union|Enum|Typedef/)
20197 { # repair complex types first
20198 next;
20199 }
20200
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020201 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020202 {
20203 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20204 if($BType=~/Struct|Union|Enum/i)
20205 {
20206 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20207 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20208 }
20209 }
20210 }
20211 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20212 {
20213 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20214 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20215 if($TType=~/Struct|Union|Enum/) {
20216 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20217 }
20218 }
20219 }
20220
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020221 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020222 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020223 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20224 { # support for old ABI dumps < 2.0 (ACC 1.22)
20225 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20226 {
20227 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20228 {
20229 if($Access ne "public") {
20230 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20231 }
20232 }
20233 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20234 }
20235 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20236 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020237 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20238 { # support for old ABI dumps
20239 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20240 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020241 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20242 { # DWARF ABI Dumps
20243 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20244 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020245 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20246 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20247 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020248 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20249 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020250 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020251 foreach (keys(%{$TInfo{"Base"}})) {
20252 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020253 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020254 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020255 if($TInfo{"Type"} eq "MethodPtr")
20256 {
20257 if(defined $TInfo{"Param"})
20258 { # support for old ABI dumps <= 1.17
20259 if(not defined $TInfo{"Param"}{"0"})
20260 {
20261 my $Max = keys(%{$TInfo{"Param"}});
20262 foreach my $Pos (1 .. $Max) {
20263 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20264 }
20265 delete($TInfo{"Param"}{$Max});
20266 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20267 }
20268 }
20269 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020270 if($TInfo{"BaseType"} eq $TypeId)
20271 { # fix ABI dump
20272 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20273 }
20274 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020275 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020276 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020277 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020278 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20279 if(not $BName)
20280 { # broken type
20281 next;
20282 }
20283 if($TInfo{"Name"} eq $BName)
20284 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020285 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020286 next;
20287 }
20288 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20289 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020290 }
20291 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020292 }
20293 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20294 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020295 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020296 }
20297 }
20298
20299 if(not checkDump($LibVersion, "2.15"))
20300 { # support for old ABI dumps
20301 my %Dups = ();
20302 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20303 {
20304 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020305 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020306 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20307 { # remove template decls
20308 delete($SymbolInfo{$LibVersion}{$InfoId});
20309 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020311 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020312 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20313 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020314 { # templates
20315 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020316 }
20317 }
20318 }
20319
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020320 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20321 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020322 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20323 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20324 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20325 { # support for old ABI dumps (< 3.1)
20326 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20327 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20328 { # add "this" first parameter
20329 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20330 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20331
20332 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20333 {
20334 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20335 foreach my $Pos (reverse(0 .. $#Pos)) {
20336 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20337 }
20338 }
20339 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20340 }
20341 }
20342
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020343 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20344 { # ABI dumps have no mangled names for C-functions
20345 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20346 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020347 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20348 { # support for old ABI dumps
20349 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20350 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020351 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20352 { # DWARF ABI Dumps
20353 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20354 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020355 }
20356
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020357 $Descriptor{$LibVersion}{"Dump"} = 1;
20358}
20359
20360sub read_Machine_DumpInfo($$)
20361{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020362 my ($ABI, $LibVersion) = @_;
20363 if($ABI->{"Arch"}) {
20364 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020365 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020366 if($ABI->{"WordSize"}) {
20367 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020368 }
20369 else
20370 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020371 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020372 }
20373 if(not $WORD_SIZE{$LibVersion})
20374 { # support for old dumps (<1.23)
20375 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20376 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020377 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020378 }
20379 else
20380 {
20381 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020382 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020383 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020384 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20385 { # any "pointer"-type
20386 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020387 last;
20388 }
20389 }
20390 if($PSize)
20391 { # a pointer type size
20392 $WORD_SIZE{$LibVersion} = $PSize;
20393 }
20394 else {
20395 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20396 }
20397 }
20398 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020399 if($ABI->{"GccVersion"}) {
20400 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020401 }
20402}
20403
20404sub read_Libs_DumpInfo($$)
20405{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020406 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020407 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20408 if(not $Library_Symbol{$LibVersion})
20409 { # support for old dumps
20410 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20411 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020412 if(keys(%{$Library_Symbol{$LibVersion}})
20413 and not $DumpAPI) {
20414 $Descriptor{$LibVersion}{"Libs"} = "OK";
20415 }
20416}
20417
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020418sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020419{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020420 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020421
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020422 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020423 and not $DumpAPI) {
20424 $Descriptor{$LibVersion}{"Headers"} = "OK";
20425 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020426 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020427 { # headers info is stored in the old dumps in the different way
20428 if($UseOldDumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020429 and my $Name = $ABI->{"Headers"}{$Identity}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020430 { # support for old dumps: headers info corrected in 1.22
20431 $Identity = $Name;
20432 }
20433 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020434 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020435 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020436
20437 if(keys(%{$ABI->{"Sources"}})
20438 and not $DumpAPI) {
20439 $Descriptor{$LibVersion}{"Sources"} = "OK";
20440 }
20441 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
20442 { # headers info is stored in the old dumps in the different way
20443 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20444 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20445 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020446}
20447
20448sub find_libs($$$)
20449{
20450 my ($Path, $Type, $MaxDepth) = @_;
20451 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020452 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020453}
20454
20455sub createDescriptor($$)
20456{
20457 my ($LibVersion, $Path) = @_;
20458 if(not $LibVersion or not $Path
20459 or not -e $Path) {
20460 return "";
20461 }
20462 if(-d $Path)
20463 { # directory with headers files and shared objects
20464 return "
20465 <version>
20466 ".$TargetVersion{$LibVersion}."
20467 </version>
20468
20469 <headers>
20470 $Path
20471 </headers>
20472
20473 <libs>
20474 $Path
20475 </libs>";
20476 }
20477 else
20478 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020479 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020480 { # standard XML-descriptor
20481 return readFile($Path);
20482 }
20483 elsif(is_header($Path, 2, $LibVersion))
20484 { # header file
20485 return "
20486 <version>
20487 ".$TargetVersion{$LibVersion}."
20488 </version>
20489
20490 <headers>
20491 $Path
20492 </headers>
20493
20494 <libs>
20495 none
20496 </libs>";
20497 }
20498 elsif(parse_libname($Path, "name", $OStarget))
20499 { # shared object
20500 return "
20501 <version>
20502 ".$TargetVersion{$LibVersion}."
20503 </version>
20504
20505 <headers>
20506 none
20507 </headers>
20508
20509 <libs>
20510 $Path
20511 </libs>";
20512 }
20513 else
20514 { # standard XML-descriptor
20515 return readFile($Path);
20516 }
20517 }
20518}
20519
20520sub detect_lib_default_paths()
20521{
20522 my %LPaths = ();
20523 if($OSgroup eq "bsd")
20524 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020525 if(my $LdConfig = get_CmdPath("ldconfig"))
20526 {
20527 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20528 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020529 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20530 {
20531 my $Name = "lib".$1;
20532 if(not defined $LPaths{$Name}) {
20533 $LPaths{$Name} = $2;
20534 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020535 }
20536 }
20537 }
20538 else {
20539 printMsg("WARNING", "can't find ldconfig");
20540 }
20541 }
20542 else
20543 {
20544 if(my $LdConfig = get_CmdPath("ldconfig"))
20545 {
20546 if($SystemRoot and $OSgroup eq "linux")
20547 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20548 if(-e $SystemRoot."/etc/ld.so.conf") {
20549 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20550 }
20551 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020552 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20553 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020554 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20555 {
20556 my ($Name, $Path) = ($1, $2);
20557 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020558 if(not defined $LPaths{$Name})
20559 { # get first element from the list of available paths
20560
20561 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20562 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20563 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20564
20565 $LPaths{$Name} = $Path;
20566 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020567 }
20568 }
20569 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020570 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020571 printMsg("WARNING", "can't find ldconfig");
20572 }
20573 }
20574 return \%LPaths;
20575}
20576
20577sub detect_bin_default_paths()
20578{
20579 my $EnvPaths = $ENV{"PATH"};
20580 if($OSgroup eq "beos") {
20581 $EnvPaths.=":".$ENV{"BETOOLS"};
20582 }
20583 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020584 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020585 {
20586 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020587 next if(not $Path);
20588 if($SystemRoot
20589 and $Path=~/\A\Q$SystemRoot\E\//)
20590 { # do NOT use binaries from target system
20591 next;
20592 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020593 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020594 }
20595}
20596
20597sub detect_inc_default_paths()
20598{
20599 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020600 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020601 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020602 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020603 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020604 next if(index($Line, "/cc1plus ")!=-1);
20605
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020606 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20607 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020608 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020609 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020610 if(index($Path, "c++")!=-1
20611 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020612 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020613 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020614 if(not defined $MAIN_CPP_DIR
20615 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20616 $MAIN_CPP_DIR = $Path;
20617 }
20618 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020619 elsif(index($Path, "gcc")!=-1) {
20620 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020621 }
20622 else
20623 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020624 if($Path=~/local[\/\\]+include/)
20625 { # local paths
20626 next;
20627 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020628 if($SystemRoot
20629 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20630 { # The GCC include path for user headers is not a part of the system root
20631 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20632 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20633 next;
20634 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020635 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020636 }
20637 }
20638 }
20639 unlink("$TMP_DIR/empty.h");
20640 return %DPaths;
20641}
20642
20643sub detect_default_paths($)
20644{
20645 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20646 my $Search = $_[0];
20647 if($Search!~/inc/) {
20648 $HSearch = 0;
20649 }
20650 if($Search!~/lib/) {
20651 $LSearch = 0;
20652 }
20653 if($Search!~/bin/) {
20654 $BSearch = 0;
20655 }
20656 if($Search!~/gcc/) {
20657 $GSearch = 0;
20658 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020659 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020660 { # <search_headers> section of the XML descriptor
20661 # do NOT search for systems headers
20662 $HSearch = 0;
20663 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020664 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020665 { # <search_headers> section of the XML descriptor
20666 # do NOT search for systems headers
20667 $LSearch = 0;
20668 }
20669 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20670 { # additional search paths
20671 next if($Type eq "include" and not $HSearch);
20672 next if($Type eq "lib" and not $LSearch);
20673 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020674 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020675 }
20676 if($OSgroup ne "windows")
20677 { # unix-like
20678 foreach my $Type ("include", "lib", "bin")
20679 { # automatic detection of system "devel" directories
20680 next if($Type eq "include" and not $HSearch);
20681 next if($Type eq "lib" and not $LSearch);
20682 next if($Type eq "bin" and not $BSearch);
20683 my ($UsrDir, $RootDir) = ("/usr", "/");
20684 if($SystemRoot and $Type ne "bin")
20685 { # 1. search for target headers and libraries
20686 # 2. use host commands: ldconfig, readelf, etc.
20687 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20688 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020689 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020690 if(-d $RootDir."/".$Type)
20691 { # if "/lib" is symbolic link
20692 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020693 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020694 }
20695 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020696 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020697 }
20698 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020699 if(-d $UsrDir)
20700 {
20701 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020702 if(-d $UsrDir."/".$Type)
20703 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020704 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020705 }
20706 }
20707 }
20708 }
20709 if($BSearch)
20710 {
20711 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020712 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020713 }
20714 # check environment variables
20715 if($OSgroup eq "beos")
20716 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020717 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020718 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020719 if($_ eq ".") {
20720 next;
20721 }
20722 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20723 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20724 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020725 }
20726 }
20727 if($HSearch)
20728 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020729 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20730 split(/:|;/, $ENV{"BEINCLUDES"})
20731 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020732 }
20733 if($LSearch)
20734 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020735 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20736 split(/:|;/, $ENV{"BELIBRARIES"}),
20737 split(/:|;/, $ENV{"LIBRARY_PATH"})
20738 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020739 }
20740 }
20741 if($LSearch)
20742 { # using linker to get system paths
20743 if(my $LPaths = detect_lib_default_paths())
20744 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020745 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020746 foreach my $Name (keys(%{$LPaths}))
20747 {
20748 if($SystemRoot
20749 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20750 { # wrong ldconfig configuration
20751 # check your <sysroot>/etc/ld.so.conf
20752 next;
20753 }
20754 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020755 if(my $Dir = get_dirname($LPaths->{$Name})) {
20756 $Dirs{$Dir} = 1;
20757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020758 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020759 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020760 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020761 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020762 }
20763 if($BSearch)
20764 {
20765 if($CrossGcc)
20766 { # --cross-gcc=arm-linux-gcc
20767 if(-e $CrossGcc)
20768 { # absolute or relative path
20769 $GCC_PATH = get_abs_path($CrossGcc);
20770 }
20771 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20772 { # command name
20773 $GCC_PATH = $CrossGcc;
20774 }
20775 else {
20776 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20777 }
20778 if($GCC_PATH=~/\s/) {
20779 $GCC_PATH = "\"".$GCC_PATH."\"";
20780 }
20781 }
20782 }
20783 if($GSearch)
20784 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020785 if(not $CrossGcc)
20786 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020787 $GCC_PATH = get_CmdPath("gcc");
20788 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020789 if(not $GCC_PATH)
20790 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020791 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020792 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020793 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020794 { # select the latest version
20795 @GCCs = sort {$b cmp $a} @GCCs;
20796 if(check_gcc($GCCs[0], "3"))
20797 {
20798 $GCC_PATH = $GCCs[0];
20799 last;
20800 }
20801 }
20802 }
20803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020804 if(not $GCC_PATH) {
20805 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20806 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020807
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020808 if(not $CheckObjectsOnly_Opt)
20809 {
20810 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
20811 {
20812 my $GccTarget = get_dumpmachine($GCC_PATH);
20813 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget)");
20814 if($GccTarget=~/symbian/)
20815 {
20816 $OStarget = "symbian";
20817 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20818 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020819
20820 # check GCC version
20821 if($GCC_Ver=~/\A4\.8(|\.0|\.1)\Z/)
20822 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
20823 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20824 $EMERGENCY_MODE_48 = 1;
20825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020826 }
20827 else {
20828 exitStatus("Error", "something is going wrong with the GCC compiler");
20829 }
20830 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020831 if($HSearch)
20832 {
20833 if(not $NoStdInc)
20834 { # do NOT search in GCC standard paths
20835 my %DPaths = detect_inc_default_paths();
20836 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20837 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20838 @DefaultIncPaths = @{$DPaths{"Inc"}};
20839 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020840 }
20841 }
20842 }
20843 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020844 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020845 my $IncPath = "/usr/include";
20846 if($SystemRoot) {
20847 $IncPath = $SystemRoot.$IncPath;
20848 }
20849 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020850 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020851 }
20852 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020853
20854 if($ExtraInfo)
20855 {
20856 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20857 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20858 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020859}
20860
20861sub getLIB_EXT($)
20862{
20863 my $Target = $_[0];
20864 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20865 return $Ext;
20866 }
20867 return $OS_LibExt{$LIB_TYPE}{"default"};
20868}
20869
20870sub getAR_EXT($)
20871{
20872 my $Target = $_[0];
20873 if(my $Ext = $OS_Archive{$Target}) {
20874 return $Ext;
20875 }
20876 return $OS_Archive{"default"};
20877}
20878
20879sub get_dumpversion($)
20880{
20881 my $Cmd = $_[0];
20882 return "" if(not $Cmd);
20883 if($Cache{"get_dumpversion"}{$Cmd}) {
20884 return $Cache{"get_dumpversion"}{$Cmd};
20885 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020886 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020887 chomp($V);
20888 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20889}
20890
20891sub get_dumpmachine($)
20892{
20893 my $Cmd = $_[0];
20894 return "" if(not $Cmd);
20895 if($Cache{"get_dumpmachine"}{$Cmd}) {
20896 return $Cache{"get_dumpmachine"}{$Cmd};
20897 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020898 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020899 chomp($Machine);
20900 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20901}
20902
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020903sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020904{
20905 my $Cmd = $_[0];
20906 return "" if(not $Cmd);
20907 my @Options = (
20908 "--version",
20909 "-help"
20910 );
20911 foreach my $Opt (@Options)
20912 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020913 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020914 if($Info) {
20915 return 1;
20916 }
20917 }
20918 return 0;
20919}
20920
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020921sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020922{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020923 my ($Cmd, $ReqVer) = @_;
20924 return 0 if(not $Cmd or not $ReqVer);
20925 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20926 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020927 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020928 if(my $GccVer = get_dumpversion($Cmd))
20929 {
20930 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20931 if(cmpVersions($GccVer, $ReqVer)>=0) {
20932 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20933 }
20934 }
20935 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020936}
20937
20938sub get_depth($)
20939{
20940 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020941 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020942 }
20943 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20944}
20945
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020946sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020947{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020948 return if($Cache{"registerGccHeaders"}); # this function should be called once
20949
20950 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020951 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020952 my @Headers = cmd_find($Path,"f");
20953 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20954 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020955 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020956 my $FileName = get_filename($HPath);
20957 if(not defined $DefaultGccHeader{$FileName})
20958 { # skip duplicated
20959 $DefaultGccHeader{$FileName} = $HPath;
20960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020961 }
20962 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020963 $Cache{"registerGccHeaders"} = 1;
20964}
20965
20966sub registerCppHeaders()
20967{
20968 return if($Cache{"registerCppHeaders"}); # this function should be called once
20969
20970 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020971 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020972 my @Headers = cmd_find($CppDir,"f");
20973 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20974 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020975 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020976 my $FileName = get_filename($Path);
20977 if(not defined $DefaultCppHeader{$FileName})
20978 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020979 $DefaultCppHeader{$FileName} = $Path;
20980 }
20981 }
20982 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020983 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020984}
20985
20986sub parse_libname($$$)
20987{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020988 return "" if(not $_[0]);
20989 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20990 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020991 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020992 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20993}
20994
20995sub parse_libname_I($$$)
20996{
20997 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020998
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020999 if($Target eq "symbian") {
21000 return parse_libname_symbian($Name, $Type);
21001 }
21002 elsif($Target eq "windows") {
21003 return parse_libname_windows($Name, $Type);
21004 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021005
21006 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021007 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021008 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021009 { # libSDL-1.2.so.0.7.1
21010 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021011 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021012 if($Type eq "name")
21013 { # libSDL-1.2
21014 # libwbxml2
21015 return $2;
21016 }
21017 elsif($Type eq "name+ext")
21018 { # libSDL-1.2.so
21019 # libwbxml2.so
21020 return $1;
21021 }
21022 elsif($Type eq "version")
21023 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021024 if(defined $7
21025 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021026 { # 0.7.1
21027 return $7;
21028 }
21029 else
21030 { # libc-2.5.so (=>2.5 version)
21031 my $MV = $5;
21032 $MV=~s/\A[\-\_]+//g;
21033 return $MV;
21034 }
21035 }
21036 elsif($Type eq "short")
21037 { # libSDL
21038 # libwbxml2
21039 return $3;
21040 }
21041 elsif($Type eq "shortest")
21042 { # SDL
21043 # wbxml
21044 return shortest_name($3);
21045 }
21046 }
21047 return "";# error
21048}
21049
21050sub parse_libname_symbian($$)
21051{
21052 my ($Name, $Type) = @_;
21053 my $Ext = getLIB_EXT("symbian");
21054 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21055 { # libpthread{00010001}.dso
21056 if($Type eq "name")
21057 { # libpthread{00010001}
21058 return $2;
21059 }
21060 elsif($Type eq "name+ext")
21061 { # libpthread{00010001}.dso
21062 return $1;
21063 }
21064 elsif($Type eq "version")
21065 { # 00010001
21066 my $V = $4;
21067 $V=~s/\{(.+)\}/$1/;
21068 return $V;
21069 }
21070 elsif($Type eq "short")
21071 { # libpthread
21072 return $3;
21073 }
21074 elsif($Type eq "shortest")
21075 { # pthread
21076 return shortest_name($3);
21077 }
21078 }
21079 return "";# error
21080}
21081
21082sub parse_libname_windows($$)
21083{
21084 my ($Name, $Type) = @_;
21085 my $Ext = getLIB_EXT("windows");
21086 if($Name=~/((.+?)\.$Ext)\Z/)
21087 { # netapi32.dll
21088 if($Type eq "name")
21089 { # netapi32
21090 return $2;
21091 }
21092 elsif($Type eq "name+ext")
21093 { # netapi32.dll
21094 return $1;
21095 }
21096 elsif($Type eq "version")
21097 { # DLL version embedded
21098 # at binary-level
21099 return "";
21100 }
21101 elsif($Type eq "short")
21102 { # netapi32
21103 return $2;
21104 }
21105 elsif($Type eq "shortest")
21106 { # netapi
21107 return shortest_name($2);
21108 }
21109 }
21110 return "";# error
21111}
21112
21113sub shortest_name($)
21114{
21115 my $Name = $_[0];
21116 # remove prefix
21117 $Name=~s/\A(lib|open)//;
21118 # remove suffix
21119 $Name=~s/[\W\d_]+\Z//i;
21120 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21121 return $Name;
21122}
21123
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021124sub createSymbolsList($$$$$)
21125{
21126 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
21127 read_ABI_Dump(1, $DPath);
21128 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021129 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021130 }
21131 my %SymbolHeaderLib = ();
21132 my $Total = 0;
21133 # Get List
21134 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21135 {
21136 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021137 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021138 next;
21139 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021140 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021141 { # skip other symbols
21142 next;
21143 }
21144 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21145 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021146 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021147 next;
21148 }
21149 my $DyLib = $Symbol_Library{1}{$Symbol};
21150 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021151 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021152 next;
21153 }
21154 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21155 $Total+=1;
21156 }
21157 # Draw List
21158 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21159 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21160 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21161 {
21162 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21163 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021164 my %NS_Symbol = ();
21165 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021166 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021167 }
21168 foreach my $NameSpace (sort keys(%NS_Symbol))
21169 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021170 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021171 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21172 foreach my $Symbol (@SortedInterfaces)
21173 {
21174 my $SubReport = "";
21175 my $Signature = get_Signature($Symbol, 1);
21176 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021177 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021178 }
21179 if($Symbol=~/\A(_Z|\?)/)
21180 {
21181 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021182 $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 +040021183 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021184 else {
21185 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21186 }
21187 }
21188 else
21189 {
21190 if($Signature) {
21191 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21192 }
21193 else {
21194 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21195 }
21196 }
21197 $SYMBOLS_LIST .= $SubReport;
21198 }
21199 }
21200 $SYMBOLS_LIST .= "<br/>\n";
21201 }
21202 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021203 # clear info
21204 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21205 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21206 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21207 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021208 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021209 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021210 my $CssStyles = readModule("Styles", "SymbolsList.css");
21211 my $JScripts = readModule("Scripts", "Sections.js");
21212 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021213 my $Title = "$LName: public symbols";
21214 my $Keywords = "$LName, API, symbols";
21215 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021216 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021217 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021218 <br/><br/><hr/>\n".getReportFooter($LName, 1)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021219 <div style='height:999px;'></div></body></html>";
21220 writeFile($SaveTo, $SYMBOLS_LIST);
21221}
21222
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021223sub add_target_libs($)
21224{
21225 foreach (@{$_[0]}) {
21226 $TargetLibs{$_} = 1;
21227 }
21228}
21229
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021230sub is_target_lib($)
21231{
21232 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021233 if(not $LName) {
21234 return 0;
21235 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021236 if($TargetLibraryName
21237 and $LName!~/\Q$TargetLibraryName\E/) {
21238 return 0;
21239 }
21240 if(keys(%TargetLibs)
21241 and not $TargetLibs{$LName}
21242 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21243 return 0;
21244 }
21245 return 1;
21246}
21247
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021248sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021249{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021250 my ($H, $V) = @_;
21251 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021252 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021253 if($TargetHeaders{$V}{$H}) {
21254 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021255 }
21256 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021257 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021258}
21259
21260sub checkVersionNum($$)
21261{
21262 my ($LibVersion, $Path) = @_;
21263 if(my $VerNum = $TargetVersion{$LibVersion}) {
21264 return $VerNum;
21265 }
21266 my $UsedAltDescr = 0;
21267 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021268 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021269 next if(isDump($Part)); # ABI dump
21270 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021271 my $VerNum = "";
21272 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021273 {
21274 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021275 $VerNum = parse_libname($Part, "version", $OStarget);
21276 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021277 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021278 }
21279 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021280 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
21281 {
21282 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021283 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021284 }
21285 if($VerNum ne "")
21286 {
21287 $TargetVersion{$LibVersion} = $VerNum;
21288 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021289 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021290 }
21291 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021292 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 +040021293 }
21294 return $TargetVersion{$LibVersion};
21295 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021296 }
21297 if($UsedAltDescr)
21298 {
21299 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021300 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021301 }
21302 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021303 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021304 }
21305 }
21306}
21307
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021308sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021309{
21310 my $Str = $_[0];
21311 return "" if(not $Str);
21312 $Str=~s/\Q$TargetLibraryName\E//g;
21313 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021314 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021315 return $2;
21316 }
21317 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
21318 return $V;
21319 }
21320 return "";
21321}
21322
21323sub readLibs($)
21324{
21325 my $LibVersion = $_[0];
21326 if($OStarget eq "windows")
21327 { # dumpbin.exe will crash
21328 # without VS Environment
21329 check_win32_env();
21330 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021331 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021332 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021333 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021334}
21335
21336sub dump_sorting($)
21337{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021338 my $Hash = $_[0];
21339 return [] if(not $Hash);
21340 my @Keys = keys(%{$Hash});
21341 return [] if($#Keys<0);
21342 if($Keys[0]=~/\A\d+\Z/)
21343 { # numbers
21344 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021345 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021346 else
21347 { # strings
21348 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021349 }
21350}
21351
21352sub printMsg($$)
21353{
21354 my ($Type, $Msg) = @_;
21355 if($Type!~/\AINFO/) {
21356 $Msg = $Type.": ".$Msg;
21357 }
21358 if($Type!~/_C\Z/) {
21359 $Msg .= "\n";
21360 }
21361 if($Quiet)
21362 { # --quiet option
21363 appendFile($COMMON_LOG_PATH, $Msg);
21364 }
21365 else
21366 {
21367 if($Type eq "ERROR") {
21368 print STDERR $Msg;
21369 }
21370 else {
21371 print $Msg;
21372 }
21373 }
21374}
21375
21376sub exitStatus($$)
21377{
21378 my ($Code, $Msg) = @_;
21379 printMsg("ERROR", $Msg);
21380 exit($ERROR_CODE{$Code});
21381}
21382
21383sub exitReport()
21384{ # the tool has run without any errors
21385 printReport();
21386 if($COMPILE_ERRORS)
21387 { # errors in headers may add false positives/negatives
21388 exit($ERROR_CODE{"Compile_Error"});
21389 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021390 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21391 { # --binary
21392 exit($ERROR_CODE{"Incompatible"});
21393 }
21394 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21395 { # --source
21396 exit($ERROR_CODE{"Incompatible"});
21397 }
21398 elsif($RESULT{"Source"}{"Problems"}
21399 or $RESULT{"Binary"}{"Problems"})
21400 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021401 exit($ERROR_CODE{"Incompatible"});
21402 }
21403 else {
21404 exit($ERROR_CODE{"Compatible"});
21405 }
21406}
21407
21408sub readRules($)
21409{
21410 my $Kind = $_[0];
21411 if(not -f $RULES_PATH{$Kind}) {
21412 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21413 }
21414 my $Content = readFile($RULES_PATH{$Kind});
21415 while(my $Rule = parseTag(\$Content, "rule"))
21416 {
21417 my $RId = parseTag(\$Rule, "id");
21418 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21419 foreach my $Prop (@Properties) {
21420 if(my $Value = parseTag(\$Rule, lc($Prop)))
21421 {
21422 $Value=~s/\n[ ]*//;
21423 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21424 }
21425 }
21426 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21427 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21428 }
21429 else {
21430 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21431 }
21432 }
21433}
21434
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021435sub getReportPath($)
21436{
21437 my $Level = $_[0];
21438 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21439 if($Level eq "Binary")
21440 {
21441 if($BinaryReportPath)
21442 { # --bin-report-path
21443 return $BinaryReportPath;
21444 }
21445 elsif($OutputReportPath)
21446 { # --report-path
21447 return $OutputReportPath;
21448 }
21449 else
21450 { # default
21451 return $Dir."/abi_compat_report.$ReportFormat";
21452 }
21453 }
21454 elsif($Level eq "Source")
21455 {
21456 if($SourceReportPath)
21457 { # --src-report-path
21458 return $SourceReportPath;
21459 }
21460 elsif($OutputReportPath)
21461 { # --report-path
21462 return $OutputReportPath;
21463 }
21464 else
21465 { # default
21466 return $Dir."/src_compat_report.$ReportFormat";
21467 }
21468 }
21469 else
21470 {
21471 if($OutputReportPath)
21472 { # --report-path
21473 return $OutputReportPath;
21474 }
21475 else
21476 { # default
21477 return $Dir."/compat_report.$ReportFormat";
21478 }
21479 }
21480}
21481
21482sub printStatMsg($)
21483{
21484 my $Level = $_[0];
21485 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21486}
21487
21488sub listAffected($)
21489{
21490 my $Level = $_[0];
21491 my $List = "";
21492 foreach (keys(%{$TotalAffected{$Level}}))
21493 {
21494 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21495 { # skip "Low"-severity problems
21496 next;
21497 }
21498 $List .= "$_\n";
21499 }
21500 my $Dir = get_dirname(getReportPath($Level));
21501 if($Level eq "Binary") {
21502 writeFile($Dir."/abi_affected.txt", $List);
21503 }
21504 elsif($Level eq "Source") {
21505 writeFile($Dir."/src_affected.txt", $List);
21506 }
21507}
21508
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021509sub printReport()
21510{
21511 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021512 createReport();
21513 if($JoinReport or $DoubleReport)
21514 {
21515 if($RESULT{"Binary"}{"Problems"}
21516 or $RESULT{"Source"}{"Problems"}) {
21517 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021518 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021519 else {
21520 printMsg("INFO", "result: COMPATIBLE");
21521 }
21522 printStatMsg("Binary");
21523 printStatMsg("Source");
21524 if($ListAffected)
21525 { # --list-affected
21526 listAffected("Binary");
21527 listAffected("Source");
21528 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021529 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021530 elsif($BinaryOnly)
21531 {
21532 if($RESULT{"Binary"}{"Problems"}) {
21533 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21534 }
21535 else {
21536 printMsg("INFO", "result: COMPATIBLE");
21537 }
21538 printStatMsg("Binary");
21539 if($ListAffected)
21540 { # --list-affected
21541 listAffected("Binary");
21542 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021543 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021544 elsif($SourceOnly)
21545 {
21546 if($RESULT{"Source"}{"Problems"}) {
21547 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21548 }
21549 else {
21550 printMsg("INFO", "result: COMPATIBLE");
21551 }
21552 printStatMsg("Source");
21553 if($ListAffected)
21554 { # --list-affected
21555 listAffected("Source");
21556 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021557 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021558 if($StdOut)
21559 {
21560 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021561 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021562 printMsg("INFO", "compatibility report has been generated to stdout");
21563 }
21564 else
21565 { # default
21566 printMsg("INFO", "compatibility reports have been generated to stdout");
21567 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021568 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021569 else
21570 {
21571 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021572 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021573 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21574 }
21575 elsif($DoubleReport)
21576 { # default
21577 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21578 }
21579 elsif($BinaryOnly)
21580 { # --binary
21581 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21582 }
21583 elsif($SourceOnly)
21584 { # --source
21585 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21586 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021587 }
21588}
21589
21590sub check_win32_env()
21591{
21592 if(not $ENV{"DevEnvDir"}
21593 or not $ENV{"LIB"}) {
21594 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21595 }
21596}
21597
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021598sub diffSets($$)
21599{
21600 my ($S1, $S2) = @_;
21601 my @SK1 = keys(%{$S1});
21602 my @SK2 = keys(%{$S2});
21603 if($#SK1!=$#SK2) {
21604 return 1;
21605 }
21606 foreach my $K1 (@SK1)
21607 {
21608 if(not defined $S2->{$K1}) {
21609 return 1;
21610 }
21611 }
21612 return 0;
21613}
21614
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021615sub create_ABI_Dump()
21616{
21617 if(not -e $DumpAPI) {
21618 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21619 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021620 my @DParts = split(/\s*,\s*/, $DumpAPI);
21621 foreach my $Part (@DParts)
21622 {
21623 if(not -e $Part) {
21624 exitStatus("Access_Error", "can't access \'$Part\'");
21625 }
21626 }
21627 checkVersionNum(1, $DumpAPI);
21628 foreach my $Part (@DParts)
21629 {
21630 if(isDump($Part)) {
21631 read_ABI_Dump(1, $Part);
21632 }
21633 else {
21634 readDescriptor(1, createDescriptor(1, $Part));
21635 }
21636 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021637
21638 if(not $Descriptor{1}{"Version"})
21639 { # set to default: X
21640 $Descriptor{1}{"Version"} = "X";
21641 }
21642
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021643 initLogging(1);
21644 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021645
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021646 my $DumpPath = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi";
21647 $DumpPath .= ".".$AR_EXT; # gzipped by default
21648 if($OutputDumpPath)
21649 { # user defined path
21650 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021651 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021652 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21653
21654 if(not $Archive and not $StdOut)
21655 { # check archive utilities
21656 if($OSgroup eq "windows")
21657 { # using zip
21658 my $ZipCmd = get_CmdPath("zip");
21659 if(not $ZipCmd) {
21660 exitStatus("Not_Found", "can't find \"zip\"");
21661 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021662 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021663 else
21664 { # using tar and gzip
21665 my $TarCmd = get_CmdPath("tar");
21666 if(not $TarCmd) {
21667 exitStatus("Not_Found", "can't find \"tar\"");
21668 }
21669 my $GzipCmd = get_CmdPath("gzip");
21670 if(not $GzipCmd) {
21671 exitStatus("Not_Found", "can't find \"gzip\"");
21672 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021673 }
21674 }
21675
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021676 if(not $Descriptor{1}{"Dump"})
21677 {
21678 if(not $CheckHeadersOnly) {
21679 readLibs(1);
21680 }
21681 if($CheckHeadersOnly) {
21682 setLanguage(1, "C++");
21683 }
21684 if(not $CheckObjectsOnly) {
21685 searchForHeaders(1);
21686 }
21687 $WORD_SIZE{1} = detectWordSize();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021688 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021689 if(not $Descriptor{1}{"Dump"})
21690 {
21691 if($Descriptor{1}{"Headers"}) {
21692 readHeaders(1);
21693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021694 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021695 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021696 if(not keys(%{$SymbolInfo{1}}))
21697 { # check if created dump is valid
21698 if(not $ExtendedCheck and not $CheckObjectsOnly)
21699 {
21700 if($CheckHeadersOnly) {
21701 exitStatus("Empty_Set", "the set of public symbols is empty");
21702 }
21703 else {
21704 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21705 }
21706 }
21707 }
21708 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021709 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021710 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21711 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021712 if($ExtraDump)
21713 { # add unmangled names to the ABI dump
21714 my @Names = ();
21715 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21716 {
21717 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21718 push(@Names, $MnglName);
21719 }
21720 }
21721 translateSymbols(@Names, 1);
21722 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21723 {
21724 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21725 {
21726 if(my $Unmangled = $tr_name{$MnglName})
21727 {
21728 if($MnglName ne $Unmangled) {
21729 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21730 }
21731 }
21732 }
21733 }
21734 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021735
21736 my %GccConstants = (); # built-in GCC constants
21737 foreach my $Name (keys(%{$Constants{1}}))
21738 {
21739 if(not defined $Constants{1}{$Name}{"Header"})
21740 {
21741 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21742 delete($Constants{1}{$Name});
21743 }
21744 }
21745
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021746 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021747 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021748 "TypeInfo" => $TypeInfo{1},
21749 "SymbolInfo" => $SymbolInfo{1},
21750 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021751 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021752 "SymbolVersion" => $SymVer{1},
21753 "LibraryVersion" => $Descriptor{1}{"Version"},
21754 "LibraryName" => $TargetLibraryName,
21755 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021756 "SkipTypes" => $SkipTypes{1},
21757 "SkipSymbols" => $SkipSymbols{1},
21758 "SkipNameSpaces" => $SkipNameSpaces{1},
21759 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021760 "Headers" => \%HeadersInfo,
21761 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021762 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021763 "NameSpaces" => $NestedNameSpaces{1},
21764 "Target" => $OStarget,
21765 "Arch" => getArch(1),
21766 "WordSize" => $WORD_SIZE{1},
21767 "GccVersion" => get_dumpversion($GCC_PATH),
21768 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21769 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21770 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021771 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021772 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021773 }
21774 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021775 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021776 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021777 if($ExtendedCheck)
21778 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021779 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021780 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021781 if($BinaryOnly)
21782 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021783 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021784 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021785 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021786 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021787 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021788 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21789 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021790 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021791
21792 my $ABI_DUMP = "";
21793 if($UseXML)
21794 {
21795 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021796 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021797 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021798 else
21799 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021800 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021801 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021802 if($StdOut)
21803 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021804 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021805 printMsg("INFO", "ABI dump has been generated to stdout");
21806 return;
21807 }
21808 else
21809 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021810 my ($DDir, $DName) = separate_path($DumpPath);
21811 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021812 if(not $Archive) {
21813 $DPath = $DumpPath;
21814 }
21815
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021816 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021817
21818 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021819 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021820 close(DUMP);
21821
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021822 if(not -s $DPath) {
21823 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21824 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021825 if($Archive) {
21826 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021827 }
21828
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021829 if($OutputDumpPath) {
21830 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021831 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021832 else {
21833 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21834 }
21835 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 +040021836 }
21837}
21838
21839sub quickEmptyReports()
21840{ # Quick "empty" reports
21841 # 4 times faster than merging equal dumps
21842 # NOTE: the dump contains the "LibraryVersion" attribute
21843 # if you change the version, then your dump will be different
21844 # OVERCOME: use -v1 and v2 options for comparing dumps
21845 # and don't change version in the XML descriptor (and dumps)
21846 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21847 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21848 {
21849 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21850 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21851 if($FilePath1 and $FilePath2)
21852 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021853 my $Line = readLineNum($FilePath1, 0);
21854 if($Line=~/xml/)
21855 { # XML format
21856 # is not supported yet
21857 return;
21858 }
21859
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021860 local $/ = undef;
21861
21862 open(DUMP1, $FilePath1);
21863 my $Content1 = <DUMP1>;
21864 close(DUMP1);
21865
21866 open(DUMP2, $FilePath2);
21867 my $Content2 = <DUMP2>;
21868 close(DUMP2);
21869
21870 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021871 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021872 # clean memory
21873 undef $Content2;
21874
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021875 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021876 my $ABIdump = eval($Content1);
21877
21878 # clean memory
21879 undef $Content1;
21880
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021881 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021882 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 +040021883 }
21884 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021885 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021886 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21887 }
21888 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021889 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021890 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21891 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021892 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021893 read_Libs_DumpInfo($ABIdump, 1);
21894 read_Machine_DumpInfo($ABIdump, 1);
21895 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021896
21897 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21898 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21899
21900 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21901 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21902
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021903 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21904 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21905 exitReport();
21906 }
21907 }
21908 }
21909}
21910
21911sub initLogging($)
21912{
21913 my $LibVersion = $_[0];
21914 # create log directory
21915 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21916 if($OutputLogPath{$LibVersion})
21917 { # user-defined by -log-path option
21918 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21919 }
21920 if($LogMode ne "n") {
21921 mkpath($LOG_DIR);
21922 }
21923 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021924 if($Debug)
21925 { # debug directory
21926 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021927
21928 if(not $ExtraInfo)
21929 { # enable --extra-info
21930 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21931 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021932 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021933 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021934}
21935
21936sub writeLog($$)
21937{
21938 my ($LibVersion, $Msg) = @_;
21939 if($LogMode ne "n") {
21940 appendFile($LOG_PATH{$LibVersion}, $Msg);
21941 }
21942}
21943
21944sub resetLogging($)
21945{
21946 my $LibVersion = $_[0];
21947 if($LogMode!~/a|n/)
21948 { # remove old log
21949 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021950 if($Debug) {
21951 rmtree($DEBUG_PATH{$LibVersion});
21952 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021953 }
21954}
21955
21956sub printErrorLog($)
21957{
21958 my $LibVersion = $_[0];
21959 if($LogMode ne "n") {
21960 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21961 }
21962}
21963
21964sub isDump($)
21965{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021966 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz|\.zip|\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021967 return $1;
21968 }
21969 return 0;
21970}
21971
21972sub isDump_U($)
21973{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021974 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021975 return $1;
21976 }
21977 return 0;
21978}
21979
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021980sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021981{
21982 # read input XML descriptors or ABI dumps
21983 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021984 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021985 }
21986 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
21987 foreach my $Part (@DParts1)
21988 {
21989 if(not -e $Part) {
21990 exitStatus("Access_Error", "can't access \'$Part\'");
21991 }
21992 }
21993 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021994 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021995 }
21996 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
21997 foreach my $Part (@DParts2)
21998 {
21999 if(not -e $Part) {
22000 exitStatus("Access_Error", "can't access \'$Part\'");
22001 }
22002 }
22003 detect_default_paths("bin"); # to extract dumps
22004 if($#DParts1==0 and $#DParts2==0
22005 and isDump($Descriptor{1}{"Path"})
22006 and isDump($Descriptor{2}{"Path"}))
22007 { # optimization: equal ABI dumps
22008 quickEmptyReports();
22009 }
22010 checkVersionNum(1, $Descriptor{1}{"Path"});
22011 checkVersionNum(2, $Descriptor{2}{"Path"});
22012 printMsg("INFO", "preparation, please wait ...");
22013 foreach my $Part (@DParts1)
22014 {
22015 if(isDump($Part)) {
22016 read_ABI_Dump(1, $Part);
22017 }
22018 else {
22019 readDescriptor(1, createDescriptor(1, $Part));
22020 }
22021 }
22022 foreach my $Part (@DParts2)
22023 {
22024 if(isDump($Part)) {
22025 read_ABI_Dump(2, $Part);
22026 }
22027 else {
22028 readDescriptor(2, createDescriptor(2, $Part));
22029 }
22030 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022031
22032 if(not $Descriptor{1}{"Version"})
22033 { # set to default: X
22034 $Descriptor{1}{"Version"} = "X";
22035 }
22036
22037 if(not $Descriptor{2}{"Version"})
22038 { # set to default: Y
22039 $Descriptor{2}{"Version"} = "Y";
22040 }
22041
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022042 initLogging(1);
22043 initLogging(2);
22044 # check consistency
22045 if(not $Descriptor{1}{"Headers"}
22046 and not $Descriptor{1}{"Libs"}) {
22047 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
22048 }
22049 if(not $Descriptor{2}{"Headers"}
22050 and not $Descriptor{2}{"Libs"}) {
22051 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
22052 }
22053 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
22054 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
22055 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
22056 }
22057 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
22058 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
22059 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
22060 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022061 if(not $Descriptor{1}{"Headers"})
22062 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022063 if($CheckHeadersOnly_Opt) {
22064 exitStatus("Error", "can't find header files info in descriptor d1");
22065 }
22066 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022067 if(not $Descriptor{2}{"Headers"})
22068 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022069 if($CheckHeadersOnly_Opt) {
22070 exitStatus("Error", "can't find header files info in descriptor d2");
22071 }
22072 }
22073 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022074 or not $Descriptor{2}{"Headers"})
22075 {
22076 if(not $CheckObjectsOnly_Opt)
22077 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022078 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
22079 $CheckObjectsOnly = 1;
22080 }
22081 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022082 if(not $Descriptor{1}{"Libs"})
22083 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022084 if($CheckObjectsOnly_Opt) {
22085 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
22086 }
22087 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022088 if(not $Descriptor{2}{"Libs"})
22089 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022090 if($CheckObjectsOnly_Opt) {
22091 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
22092 }
22093 }
22094 if(not $Descriptor{1}{"Libs"}
22095 or not $Descriptor{2}{"Libs"})
22096 { # comparing standalone header files
22097 # comparing ABI dumps created with --headers-only
22098 if(not $CheckHeadersOnly_Opt)
22099 {
22100 printMsg("WARNING", "checking headers only");
22101 $CheckHeadersOnly = 1;
22102 }
22103 }
22104 if($UseDumps)
22105 { # --use-dumps
22106 # parallel processing
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022107 my $DumpPath1 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi.$AR_EXT";
22108 my $DumpPath2 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{2}{"Version"}.".abi.$AR_EXT";
22109
22110 unlink($DumpPath1);
22111 unlink($DumpPath2);
22112
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022113 my $pid = fork();
22114 if($pid)
22115 { # dump on two CPU cores
22116 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22117 if($RelativeDirectory{1}) {
22118 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22119 }
22120 if($OutputLogPath{1}) {
22121 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22122 }
22123 if($CrossGcc) {
22124 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22125 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022126 if($Quiet)
22127 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022128 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022129 @PARAMS = (@PARAMS, "-logging-mode", "a");
22130 }
22131 elsif($LogMode and $LogMode ne "w")
22132 { # "w" is default
22133 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022134 }
22135 if($ExtendedCheck) {
22136 @PARAMS = (@PARAMS, "-extended");
22137 }
22138 if($UserLang) {
22139 @PARAMS = (@PARAMS, "-lang", $UserLang);
22140 }
22141 if($TargetVersion{1}) {
22142 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22143 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022144 if($BinaryOnly) {
22145 @PARAMS = (@PARAMS, "-binary");
22146 }
22147 if($SourceOnly) {
22148 @PARAMS = (@PARAMS, "-source");
22149 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022150 if($SortDump) {
22151 @PARAMS = (@PARAMS, "-sort");
22152 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022153 if($DumpFormat and $DumpFormat ne "perl") {
22154 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22155 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022156 if($CheckHeadersOnly) {
22157 @PARAMS = (@PARAMS, "-headers-only");
22158 }
22159 if($CheckObjectsOnly) {
22160 @PARAMS = (@PARAMS, "-objects-only");
22161 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022162 if($Debug)
22163 {
22164 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022165 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022166 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022167 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022168 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022169 exit(1);
22170 }
22171 }
22172 else
22173 { # child
22174 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22175 if($RelativeDirectory{2}) {
22176 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22177 }
22178 if($OutputLogPath{2}) {
22179 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22180 }
22181 if($CrossGcc) {
22182 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22183 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022184 if($Quiet)
22185 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022186 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022187 @PARAMS = (@PARAMS, "-logging-mode", "a");
22188 }
22189 elsif($LogMode and $LogMode ne "w")
22190 { # "w" is default
22191 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022192 }
22193 if($ExtendedCheck) {
22194 @PARAMS = (@PARAMS, "-extended");
22195 }
22196 if($UserLang) {
22197 @PARAMS = (@PARAMS, "-lang", $UserLang);
22198 }
22199 if($TargetVersion{2}) {
22200 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22201 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022202 if($BinaryOnly) {
22203 @PARAMS = (@PARAMS, "-binary");
22204 }
22205 if($SourceOnly) {
22206 @PARAMS = (@PARAMS, "-source");
22207 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022208 if($SortDump) {
22209 @PARAMS = (@PARAMS, "-sort");
22210 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022211 if($DumpFormat and $DumpFormat ne "perl") {
22212 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22213 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022214 if($CheckHeadersOnly) {
22215 @PARAMS = (@PARAMS, "-headers-only");
22216 }
22217 if($CheckObjectsOnly) {
22218 @PARAMS = (@PARAMS, "-objects-only");
22219 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022220 if($Debug)
22221 {
22222 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022223 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022224 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022225 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022226 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022227 exit(1);
22228 }
22229 else {
22230 exit(0);
22231 }
22232 }
22233 waitpid($pid, 0);
22234 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022235 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22236 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022237 if($TargetLibraryFName ne $TargetLibraryName) {
22238 @CMP_PARAMS = (@CMP_PARAMS, "-l-full", $TargetLibraryFName);
22239 }
22240 if($ShowRetVal) {
22241 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22242 }
22243 if($CrossGcc) {
22244 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22245 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022246 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22247 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022248 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022249 }
22250 if($ReportFormat and $ReportFormat ne "html")
22251 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022252 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22253 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022254 if($OutputReportPath) {
22255 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22256 }
22257 if($BinaryReportPath) {
22258 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22259 }
22260 if($SourceReportPath) {
22261 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22262 }
22263 if($LoggingPath) {
22264 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22265 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022266 if($CheckHeadersOnly) {
22267 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22268 }
22269 if($CheckObjectsOnly) {
22270 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
22271 }
22272 if($BinaryOnly) {
22273 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22274 }
22275 if($SourceOnly) {
22276 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22277 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022278 if($Browse) {
22279 @CMP_PARAMS = (@CMP_PARAMS, "-browse", $Browse);
22280 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022281 if($OpenReport) {
22282 @CMP_PARAMS = (@CMP_PARAMS, "-open");
22283 }
22284 if($Debug)
22285 {
22286 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22287 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022288 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022289 system("perl", $0, @CMP_PARAMS);
22290 exit($?>>8);
22291 }
22292 if(not $Descriptor{1}{"Dump"}
22293 or not $Descriptor{2}{"Dump"})
22294 { # need GCC toolchain to analyze
22295 # header files and libraries
22296 detect_default_paths("inc|lib|gcc");
22297 }
22298 if(not $Descriptor{1}{"Dump"})
22299 {
22300 if(not $CheckHeadersOnly) {
22301 readLibs(1);
22302 }
22303 if($CheckHeadersOnly) {
22304 setLanguage(1, "C++");
22305 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022306 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022307 searchForHeaders(1);
22308 }
22309 $WORD_SIZE{1} = detectWordSize();
22310 }
22311 if(not $Descriptor{2}{"Dump"})
22312 {
22313 if(not $CheckHeadersOnly) {
22314 readLibs(2);
22315 }
22316 if($CheckHeadersOnly) {
22317 setLanguage(2, "C++");
22318 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022319 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022320 searchForHeaders(2);
22321 }
22322 $WORD_SIZE{2} = detectWordSize();
22323 }
22324 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22325 { # support for old ABI dumps
22326 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022327 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022328 {
22329 $WORD_SIZE{1} = $WORD_SIZE{2};
22330 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22331 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022332 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022333 {
22334 $WORD_SIZE{2} = $WORD_SIZE{1};
22335 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22336 }
22337 }
22338 elsif(not $WORD_SIZE{1}
22339 and not $WORD_SIZE{2})
22340 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022341 $WORD_SIZE{1} = "4";
22342 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022343 }
22344 if($Descriptor{1}{"Dump"})
22345 { # support for old ABI dumps
22346 prepareTypes(1);
22347 }
22348 if($Descriptor{2}{"Dump"})
22349 { # support for old ABI dumps
22350 prepareTypes(2);
22351 }
22352 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22353 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22354 }
22355 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022356 if(not $CheckObjectsOnly)
22357 {
22358 if($Descriptor{1}{"Headers"}
22359 and not $Descriptor{1}{"Dump"}) {
22360 readHeaders(1);
22361 }
22362 if($Descriptor{2}{"Headers"}
22363 and not $Descriptor{2}{"Dump"}) {
22364 readHeaders(2);
22365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022366 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022367
22368 # clean memory
22369 %SystemHeaders = ();
22370 %mangled_name_gcc = ();
22371
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022372 prepareSymbols(1);
22373 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022374
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022375 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022376 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022377
22378 # Virtual Tables
22379 registerVTable(1);
22380 registerVTable(2);
22381
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022382 if(not checkDump(1, "1.22")
22383 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022384 { # support for old ABI dumps
22385 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22386 {
22387 if($ClassName=~/</)
22388 { # templates
22389 if(not defined $VirtualTable{1}{$ClassName})
22390 { # synchronize
22391 delete($VirtualTable{2}{$ClassName});
22392 }
22393 }
22394 }
22395 }
22396
22397 registerOverriding(1);
22398 registerOverriding(2);
22399
22400 setVirtFuncPositions(1);
22401 setVirtFuncPositions(2);
22402
22403 # Other
22404 addParamNames(1);
22405 addParamNames(2);
22406
22407 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022408}
22409
22410sub compareAPIs($)
22411{
22412 my $Level = $_[0];
22413 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022414 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022415 if($Level eq "Binary") {
22416 printMsg("INFO", "comparing ABIs ...");
22417 }
22418 else {
22419 printMsg("INFO", "comparing APIs ...");
22420 }
22421 if($CheckHeadersOnly
22422 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022423 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022424 detectAdded_H($Level);
22425 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022426 }
22427 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022428 { # added/removed in libs
22429 detectAdded($Level);
22430 detectRemoved($Level);
22431 }
22432 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022433 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022434 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022435 if(keys(%{$CheckedSymbols{$Level}})) {
22436 mergeConstants($Level);
22437 }
22438 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022439
22440 $Cache{"mergeTypes"} = (); # free memory
22441
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022442 if($CheckHeadersOnly
22443 or $Level eq "Source")
22444 { # added/removed in headers
22445 mergeHeaders($Level);
22446 }
22447 else
22448 { # added/removed in libs
22449 mergeLibs($Level);
22450 if($CheckImpl
22451 and $Level eq "Binary") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022452 mergeImpl();
22453 }
22454 }
22455}
22456
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022457sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022458{
22459 my %Opts = (
22460 "OStarget"=>$OStarget,
22461 "Debug"=>$Debug,
22462 "Quiet"=>$Quiet,
22463 "LogMode"=>$LogMode,
22464 "CheckHeadersOnly"=>$CheckHeadersOnly,
22465
22466 "SystemRoot"=>$SystemRoot,
22467 "MODULES_DIR"=>$MODULES_DIR,
22468 "GCC_PATH"=>$GCC_PATH,
22469 "TargetSysInfo"=>$TargetSysInfo,
22470 "CrossPrefix"=>$CrossPrefix,
22471 "TargetLibraryName"=>$TargetLibraryName,
22472 "CrossGcc"=>$CrossGcc,
22473 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022474 "NoStdInc"=>$NoStdInc,
22475
22476 "BinaryOnly" => $BinaryOnly,
22477 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022478 );
22479 return \%Opts;
22480}
22481
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022482sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022483{
22484 my %CODE_ERROR = reverse(%ERROR_CODE);
22485 return $CODE_ERROR{$_[0]};
22486}
22487
22488sub scenario()
22489{
22490 if($StdOut)
22491 { # enable quiet mode
22492 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022493 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022494 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022495 if(not $LogMode)
22496 { # default
22497 $LogMode = "w";
22498 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022499 if($UserLang)
22500 { # --lang=C++
22501 $UserLang = uc($UserLang);
22502 $COMMON_LANGUAGE{1}=$UserLang;
22503 $COMMON_LANGUAGE{2}=$UserLang;
22504 }
22505 if($LoggingPath)
22506 {
22507 $OutputLogPath{1} = $LoggingPath;
22508 $OutputLogPath{2} = $LoggingPath;
22509 if($Quiet) {
22510 $COMMON_LOG_PATH = $LoggingPath;
22511 }
22512 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022513 if($Quick) {
22514 $ADD_TMPL_INSTANCES = 0;
22515 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022516 if($OutputDumpPath)
22517 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022518 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022519 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22520 }
22521 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022522 if($BinaryOnly and $SourceOnly)
22523 { # both --binary and --source
22524 # is the default mode
22525 $DoubleReport = 1;
22526 $JoinReport = 0;
22527 $BinaryOnly = 0;
22528 $SourceOnly = 0;
22529 if($OutputReportPath)
22530 { # --report-path
22531 $DoubleReport = 0;
22532 $JoinReport = 1;
22533 }
22534 }
22535 elsif($BinaryOnly or $SourceOnly)
22536 { # --binary or --source
22537 $DoubleReport = 0;
22538 $JoinReport = 0;
22539 }
22540 if($UseXML)
22541 { # --xml option
22542 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022543 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022544 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022545 if($ReportFormat)
22546 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022547 $ReportFormat = lc($ReportFormat);
22548 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022549 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022550 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022551 if($ReportFormat eq "htm")
22552 { # HTM == HTML
22553 $ReportFormat = "html";
22554 }
22555 elsif($ReportFormat eq "xml")
22556 { # --report-format=XML equal to --xml
22557 $UseXML = 1;
22558 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022559 }
22560 else
22561 { # default: HTML
22562 $ReportFormat = "html";
22563 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022564 if($DumpFormat)
22565 { # validate
22566 $DumpFormat = lc($DumpFormat);
22567 if($DumpFormat!~/\A(xml|perl)\Z/) {
22568 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22569 }
22570 if($DumpFormat eq "xml")
22571 { # --dump-format=XML equal to --xml
22572 $UseXML = 1;
22573 }
22574 }
22575 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022576 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022577 $DumpFormat = "perl";
22578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022579 if($Quiet and $LogMode!~/a|n/)
22580 { # --quiet log
22581 if(-f $COMMON_LOG_PATH) {
22582 unlink($COMMON_LOG_PATH);
22583 }
22584 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022585 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022586 $CheckUndefined = 1;
22587 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022588 if($TestTool and $UseDumps)
22589 { # --test && --use-dumps == --test-dump
22590 $TestDump = 1;
22591 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022592 if($Tolerant)
22593 { # enable all
22594 $Tolerance = 1234;
22595 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022596 if($Help)
22597 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022598 HELP_MESSAGE();
22599 exit(0);
22600 }
22601 if($InfoMsg) {
22602 INFO_MESSAGE();
22603 exit(0);
22604 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022605 if($ShowVersion)
22606 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022607 printMsg("INFO", "ABI Compliance Checker (ACC) $TOOL_VERSION\nCopyright (C) 2012 ROSA Laboratory\nLicense: LGPL or GPL <http://www.gnu.org/licenses/>\nThis program is free software: you can redistribute it and/or modify it.\n\nWritten by Andrey Ponomarenko.");
22608 exit(0);
22609 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022610 if($DumpVersion)
22611 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022612 printMsg("INFO", $TOOL_VERSION);
22613 exit(0);
22614 }
22615 if($ExtendedCheck) {
22616 $CheckHeadersOnly = 1;
22617 }
22618 if($SystemRoot_Opt)
22619 { # user defined root
22620 if(not -e $SystemRoot_Opt) {
22621 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22622 }
22623 $SystemRoot = $SystemRoot_Opt;
22624 $SystemRoot=~s/[\/]+\Z//g;
22625 if($SystemRoot) {
22626 $SystemRoot = get_abs_path($SystemRoot);
22627 }
22628 }
22629 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022630
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022631 if($SortDump)
22632 {
22633 $Data::Dumper::Useperl = 1;
22634 $Data::Dumper::Sortkeys = \&dump_sorting;
22635 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022636
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022637 if($TargetLibsPath)
22638 {
22639 if(not -f $TargetLibsPath) {
22640 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22641 }
22642 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22643 $TargetLibs{$Lib} = 1;
22644 }
22645 }
22646 if($TargetHeadersPath)
22647 { # --headers-list
22648 if(not -f $TargetHeadersPath) {
22649 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22650 }
22651 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22652 {
22653 $TargetHeaders{1}{$Header} = 1;
22654 $TargetHeaders{2}{$Header} = 1;
22655 }
22656 }
22657 if($TargetHeader)
22658 { # --header
22659 $TargetHeaders{1}{$TargetHeader} = 1;
22660 $TargetHeaders{2}{$TargetHeader} = 1;
22661 }
22662 if($TestTool
22663 or $TestDump)
22664 { # --test, --test-dump
22665 detect_default_paths("bin|gcc"); # to compile libs
22666 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022667 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
22668 $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022669 exit(0);
22670 }
22671 if($DumpSystem)
22672 { # --dump-system
22673 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022674 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022675 { # system XML descriptor
22676 if(not -f $DumpSystem) {
22677 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22678 }
22679 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022680 foreach (@{$Ret->{"Tools"}})
22681 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022682 push_U($SystemPaths{"bin"}, $_);
22683 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022684 }
22685 if($Ret->{"CrossPrefix"}) {
22686 $CrossPrefix = $Ret->{"CrossPrefix"};
22687 }
22688 }
22689 elsif($SystemRoot_Opt)
22690 { # -sysroot "/" option
22691 # default target: /usr/lib, /usr/include
22692 # search libs: /usr/lib and /lib
22693 if(not -e $SystemRoot."/usr/lib") {
22694 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22695 }
22696 if(not -e $SystemRoot."/lib") {
22697 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22698 }
22699 if(not -e $SystemRoot."/usr/include") {
22700 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22701 }
22702 readSystemDescriptor("
22703 <name>
22704 $DumpSystem
22705 </name>
22706 <headers>
22707 $SystemRoot/usr/include
22708 </headers>
22709 <libs>
22710 $SystemRoot/usr/lib
22711 </libs>
22712 <search_libs>
22713 $SystemRoot/lib
22714 </search_libs>");
22715 }
22716 else {
22717 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22718 }
22719 detect_default_paths("bin|gcc"); # to check symbols
22720 if($OStarget eq "windows")
22721 { # to run dumpbin.exe
22722 # and undname.exe
22723 check_win32_env();
22724 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022725 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022726 exit(0);
22727 }
22728 if($CmpSystems)
22729 { # --cmp-systems
22730 detect_default_paths("bin"); # to extract dumps
22731 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022732 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022733 exit(0);
22734 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022735 if($GenerateTemplate)
22736 {
22737 writeFile("VERSION.xml", $DescriptorTemplate."\n");
22738 printMsg("INFO", "XML-descriptor template ./VERSION.xml has been generated");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022739 exit(0);
22740 }
22741 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022742 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022743 }
22744 else
22745 { # validate library name
22746 if($TargetLibraryName=~/[\*\/\\]/) {
22747 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22748 }
22749 }
22750 if(not $TargetLibraryFName) {
22751 $TargetLibraryFName = $TargetLibraryName;
22752 }
22753 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
22754 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
22755 }
22756 if($SymbolsListPath)
22757 {
22758 if(not -f $SymbolsListPath) {
22759 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22760 }
22761 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22762 $SymbolsList{$Interface} = 1;
22763 }
22764 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022765 if($SkipSymbolsListPath)
22766 {
22767 if(not -f $SkipSymbolsListPath) {
22768 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22769 }
22770 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
22771 $SkipSymbolsList{$Interface} = 1;
22772 }
22773 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022774 if($SkipHeadersPath)
22775 {
22776 if(not -f $SkipHeadersPath) {
22777 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22778 }
22779 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022780 { # register for both versions
22781 $SkipHeadersList{1}{$Path} = 1;
22782 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022783 my ($CPath, $Type) = classifyPath($Path);
22784 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022785 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022786 }
22787 }
22788 if($ParamNamesPath)
22789 {
22790 if(not -f $ParamNamesPath) {
22791 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22792 }
22793 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22794 {
22795 if($Line=~s/\A(\w+)\;//)
22796 {
22797 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022798 if($Line=~/;(\d+);/)
22799 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022800 while($Line=~s/(\d+);(\w+)//) {
22801 $AddIntParams{$Interface}{$1}=$2;
22802 }
22803 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022804 else
22805 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022806 my $Num = 0;
22807 foreach my $Name (split(/;/, $Line)) {
22808 $AddIntParams{$Interface}{$Num++}=$Name;
22809 }
22810 }
22811 }
22812 }
22813 }
22814 if($AppPath)
22815 {
22816 if(not -f $AppPath) {
22817 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22818 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022819 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022820 $SymbolsList_App{$Interface} = 1;
22821 }
22822 }
22823 if($DumpAPI)
22824 { # --dump-abi
22825 # make an API dump
22826 create_ABI_Dump();
22827 exit($COMPILE_ERRORS);
22828 }
22829 # default: compare APIs
22830 # -d1 <path>
22831 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022832 compareInit();
22833 if($JoinReport or $DoubleReport)
22834 {
22835 compareAPIs("Binary");
22836 compareAPIs("Source");
22837 }
22838 elsif($BinaryOnly) {
22839 compareAPIs("Binary");
22840 }
22841 elsif($SourceOnly) {
22842 compareAPIs("Source");
22843 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022844 exitReport();
22845}
22846
22847scenario();