blob: c027505dde4900d7ed93e9f05b2ef9b3ddf65cac [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003# ABI Compliance Checker (ACC) 1.99.8.2
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 Ponomarenkob6a65ee2013-08-09 19:08:07 +040067my $TOOL_VERSION = "1.99.8.2";
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
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200432 This option allows one to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400433 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
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200451 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400452
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
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200496 This option allows one to specify a file with a list of symbols (mangled
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400497 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
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200651 allows one to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400652
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 Ponomarenkob6a65ee2013-08-09 19:08:07 +04003963 if(my @TParams = getTParams($TypeId, "Type")) {
3964 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3965 }
3966 else {
3967 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3968 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003969 }
3970 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3971}
3972
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003973sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003974{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003975 my $TypeId = $_[0];
3976 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003977
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003978 my %TypeAttr = ();
3979
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003980 if($TemplateDecl{$Version}{$TypeId})
3981 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003982 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003983 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003984
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003985 setTypeAccess($TypeId, \%TypeAttr);
3986 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3987 if(isBuiltIn($TypeAttr{"Header"}))
3988 {
3989 delete($TypeAttr{"Header"});
3990 delete($TypeAttr{"Line"});
3991 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003992 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003993 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3994 if(not $TypeAttr{"Name"}) {
3995 return ();
3996 }
3997 if(not $TypeAttr{"NameSpace"}) {
3998 delete($TypeAttr{"NameSpace"});
3999 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004000
4001 my $Tmpl = undef;
4002
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004003 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004004 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004005 $Tmpl = $BasicTemplate{$Version}{$TypeId};
4006
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004007 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004008 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004009 foreach my $Pos (0 .. $#TParams)
4010 {
4011 my $Val = $TParams[$Pos];
4012 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
4013
4014 if(not defined $TypeAttr{"Template"})
4015 {
4016 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
4017
4018 if($Base{"Type"} eq "TemplateParam"
4019 or defined $Base{"Template"}) {
4020 $TypeAttr{"Template"} = 1;
4021 }
4022 }
4023
4024 if($Tmpl)
4025 {
4026 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
4027 {
4028 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
4029
4030 if($Val eq $Arg) {
4031 $TypeAttr{"Template"} = 1;
4032 }
4033 }
4034 }
4035 }
4036
4037 if($Tmpl)
4038 {
4039 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
4040 {
4041 if($Pos>$#TParams)
4042 {
4043 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
4044 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
4045 }
4046 }
4047 }
4048 }
4049
4050 if($ADD_TMPL_INSTANCES)
4051 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004052 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004053 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004054 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004055 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004056 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004057 {
4058 if(my $Flds = getTreeAttr_Flds($MainInst)) {
4059 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
4060 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004061 }
4062 if(not getTreeAttr_Binf($TypeId))
4063 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004064 if(my $Binf = getTreeAttr_Binf($MainInst)) {
4065 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
4066 }
4067 }
4068 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004069 }
4070 }
4071 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004072
4073 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
4074
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004075 if(my $Size = getSize($TypeId))
4076 {
4077 $Size = $Size/$BYTE_SIZE;
4078 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004079 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004080 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004081 {
4082 if($ExtraDump)
4083 {
4084 if(not defined $TypeAttr{"Memb"}
4085 and not $Tmpl)
4086 { # declaration only
4087 $TypeAttr{"Forward"} = 1;
4088 }
4089 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004090 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004091
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004092 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004093 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004094 {
4095 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004096 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004097 }
4098 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004099 or $TypeAttr{"Type"} eq "Class")
4100 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004101 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004102 if($Skip) {
4103 return ();
4104 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004105 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004106 if(my $Algn = getAlgn($TypeId)) {
4107 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4108 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004109 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004110
4111 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4112 {
4113 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004114 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004115 {
4116 if(not isAnon($TypeAttr{"Name"})) {
4117 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4118 }
4119 }
4120 }
4121
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004122 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004123 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4124 {
4125 my @Entries = split(/\n/, $VTable);
4126 foreach (1 .. $#Entries)
4127 {
4128 my $Entry = $Entries[$_];
4129 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004130 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004131 }
4132 }
4133 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004134
4135 if($TypeAttr{"Type"} eq "Enum")
4136 {
4137 if(not $TypeAttr{"NameSpace"})
4138 {
4139 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4140 {
4141 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004142 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004143 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004144 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004145 "Header"=>$TypeAttr{"Header"}
4146 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004147 if(isAnon($TypeAttr{"Name"}))
4148 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004149 if($ExtraDump
4150 or is_target_header($TypeAttr{"Header"}, $Version))
4151 {
4152 %{$Constants{$Version}{$MName}} = (
4153 "Value" => $MVal,
4154 "Header" => $TypeAttr{"Header"}
4155 );
4156 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004157 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004158 }
4159 }
4160 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004161 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004162 {
4163 if(defined $TypedefToAnon{$TypeId}) {
4164 $TypeAttr{"AnonTypedef"} = 1;
4165 }
4166 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004167
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004168 return %TypeAttr;
4169}
4170
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004171sub simplifyVTable($)
4172{
4173 my $Content = $_[0];
4174 if($Content=~s/ \[with (.+)]//)
4175 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4176 if(my @Elems = separate_Params($1, 0, 0))
4177 {
4178 foreach my $Elem (@Elems)
4179 {
4180 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4181 {
4182 my ($Arg, $Val) = ($1, $2);
4183
4184 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4185 $Content=~s/,\s*$Arg\b//g;
4186 }
4187 else {
4188 $Content=~s/\b$Arg\b/$Val/g;
4189 }
4190 }
4191 }
4192 }
4193 }
4194
4195 return $Content;
4196}
4197
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004198sub detect_lang($)
4199{
4200 my $TypeId = $_[0];
4201 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004202 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004203 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004204 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4205 }
4206 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004207 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004208 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004209 while($Fncs)
4210 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004211 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004212 return 1;
4213 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004214 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004215 }
4216 }
4217 return 0;
4218}
4219
4220sub setSpec($$)
4221{
4222 my ($TypeId, $TypeAttr) = @_;
4223 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4224 if($Info=~/\s+spec\s+/) {
4225 $TypeAttr->{"Spec"} = 1;
4226 }
4227}
4228
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004229sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004230{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004231 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004232 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004233 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004234 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004235 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004236 my $Pos = 0;
4237 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4238 {
4239 my ($Access, $BInfoId) = ($1, $2);
4240 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004241
4242 if($ClassId==$TypeId)
4243 { # class A<N>:public A<N-1>
4244 next;
4245 }
4246
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004247 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4248 if(not $CType or $CType eq "template_type_parm"
4249 or $CType eq "typename_type")
4250 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004251 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004253 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004254 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004255 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4256 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004257 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004258 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4259 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004260 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004261 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004262 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004263 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4264 }
4265 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004266 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004267 }
4268 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004269 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004270}
4271
4272sub getBinfClassId($)
4273{
4274 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4275 $Info=~/type[ ]*:[ ]*@(\d+) /;
4276 return $1;
4277}
4278
4279sub unmangledFormat($$)
4280{
4281 my ($Name, $LibVersion) = @_;
4282 $Name = uncover_typedefs($Name, $LibVersion);
4283 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4284 $Name=~s/\(\w+\)(\d)/$1/;
4285 return $Name;
4286}
4287
4288sub modelUnmangled($$)
4289{
4290 my ($InfoId, $Compiler) = @_;
4291 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4292 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4293 }
4294 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4295 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4296 $PureSignature = "~".$PureSignature;
4297 }
4298 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4299 {
4300 my (@Params, @ParamTypes) = ();
4301 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4302 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4303 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4304 }
4305 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4306 { # checking parameters
4307 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004308 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004309 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004310 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004311
4312 if($PName eq "this"
4313 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4314 {
4315 next;
4316 }
4317
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004318 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004319 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004320 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004321 }
4322 @ParamTypes = (@ParamTypes, $PTName);
4323 }
4324 if(@ParamTypes) {
4325 $PureSignature .= "(".join(", ", @ParamTypes).")";
4326 }
4327 else
4328 {
4329 if($Compiler eq "MSVC")
4330 {
4331 $PureSignature .= "(void)";
4332 }
4333 else
4334 { # GCC
4335 $PureSignature .= "()";
4336 }
4337 }
4338 $PureSignature = delete_keywords($PureSignature);
4339 }
4340 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4341 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004342 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004343 $PureSignature = $ClassName."::".$PureSignature;
4344 }
4345 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4346 $PureSignature = $NS."::".$PureSignature;
4347 }
4348 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4349 $PureSignature .= " const";
4350 }
4351 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4352 $PureSignature .= " volatile";
4353 }
4354 my $ShowReturn = 0;
4355 if($Compiler eq "MSVC"
4356 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4357 {
4358 $ShowReturn=1;
4359 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004360 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4361 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004362 {
4363 $ShowReturn=1;
4364 }
4365 if($ShowReturn)
4366 { # mangled names for template function specializations include return value
4367 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4368 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004369 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004370 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4371 $PureSignature = $ReturnName." ".$PureSignature;
4372 }
4373 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004374 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004375}
4376
4377sub mangle_symbol($$$)
4378{ # mangling for simple methods
4379 # see gcc-4.6.0/gcc/cp/mangle.c
4380 my ($InfoId, $LibVersion, $Compiler) = @_;
4381 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4382 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4383 }
4384 my $Mangled = "";
4385 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004386 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004387 }
4388 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004389 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004390 }
4391 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4392}
4393
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004394sub mangle_symbol_MSVC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004395{
4396 my ($InfoId, $LibVersion) = @_;
4397 return "";
4398}
4399
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004400sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004401{ # see gcc-4.6.0/gcc/cp/mangle.c
4402 my ($InfoId, $LibVersion) = @_;
4403 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004404 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004405 my %Repl = ();# SN_ replacements
4406 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4407 {
4408 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4409 if($MangledClass!~/\AN/) {
4410 $MangledClass = "N".$MangledClass;
4411 }
4412 else {
4413 $MangledClass=~s/E\Z//;
4414 }
4415 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4416 $MangledClass=~s/\AN/NV/;
4417 }
4418 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4419 $MangledClass=~s/\AN/NK/;
4420 }
4421 $Mangled .= $MangledClass;
4422 }
4423 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4424 { # mangled by name due to the absence of structured info
4425 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4426 if($MangledNS!~/\AN/) {
4427 $MangledNS = "N".$MangledNS;
4428 }
4429 else {
4430 $MangledNS=~s/E\Z//;
4431 }
4432 $Mangled .= $MangledNS;
4433 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004434 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004435 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004436 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004437 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004438 foreach (@TPos) {
4439 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4440 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004441 }
4442 elsif($TmplParams)
4443 { # remangling mode
4444 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004445 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004446 }
4447 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4448 $Mangled .= "C1";
4449 }
4450 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4451 $Mangled .= "D0";
4452 }
4453 elsif($ShortName)
4454 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004455 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4456 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004457 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004458 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004459 { # "const" global data is mangled as _ZL...
4460 $Mangled .= "L";
4461 }
4462 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004463 if($ShortName=~/\Aoperator(\W.*)\Z/)
4464 {
4465 my $Op = $1;
4466 $Op=~s/\A[ ]+//g;
4467 if(my $OpMngl = $OperatorMangling{$Op}) {
4468 $Mangled .= $OpMngl;
4469 }
4470 else { # conversion operator
4471 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4472 }
4473 }
4474 else {
4475 $Mangled .= length($ShortName).$ShortName;
4476 }
4477 if(@TParams)
4478 { # templates
4479 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004480 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004481 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4482 }
4483 $Mangled .= "E";
4484 }
4485 if(not $ClassId and @TParams) {
4486 add_substitution($ShortName, \%Repl, 0);
4487 }
4488 }
4489 if($ClassId or $NameSpace) {
4490 $Mangled .= "E";
4491 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004492 if(@TParams)
4493 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004494 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004495 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4496 }
4497 }
4498 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4499 {
4500 my @Params = ();
4501 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4502 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4503 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4504 }
4505 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4506 { # checking parameters
4507 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4508 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4509 }
4510 if(not @Params) {
4511 $Mangled .= "v";
4512 }
4513 }
4514 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4515 $Mangled = write_stdcxx_substitution($Mangled);
4516 if($Mangled eq "_Z") {
4517 return "";
4518 }
4519 return $Mangled;
4520}
4521
4522sub correct_incharge($$$)
4523{
4524 my ($InfoId, $LibVersion, $Mangled) = @_;
4525 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4526 {
4527 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004528 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004529 }
4530 }
4531 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4532 {
4533 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004534 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004535 }
4536 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004537 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004538 }
4539 }
4540 return $Mangled;
4541}
4542
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004543sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004544{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004545 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004546 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004547 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004548 return $Name;
4549 }
4550 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004551 while(my $CPos = find_center($TParams, "<"))
4552 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004553 $TParams = substr($TParams, $CPos);
4554 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004555 if($TParams=~s/\A<(.+)>\Z/$1/) {
4556 $Name=~s/<\Q$TParams\E>\Z//;
4557 }
4558 else
4559 { # error
4560 $TParams = "";
4561 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004562 return ($Name, $TParams);
4563}
4564
4565sub get_sub_ns($)
4566{
4567 my $Name = $_[0];
4568 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004569 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004570 {
4571 push(@NS, substr($Name, 0, $CPos));
4572 $Name = substr($Name, $CPos);
4573 $Name=~s/\A:://;
4574 }
4575 return (join("::", @NS), $Name);
4576}
4577
4578sub mangle_ns($$$)
4579{
4580 my ($Name, $LibVersion, $Repl) = @_;
4581 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4582 {
4583 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4584 $Mangled=~s/\AN(.+)E\Z/$1/;
4585 return $Mangled;
4586
4587 }
4588 else
4589 {
4590 my ($MangledNS, $SubNS) = ("", "");
4591 ($SubNS, $Name) = get_sub_ns($Name);
4592 if($SubNS) {
4593 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4594 }
4595 $MangledNS .= length($Name).$Name;
4596 add_substitution($MangledNS, $Repl, 0);
4597 return $MangledNS;
4598 }
4599}
4600
4601sub mangle_param($$$)
4602{
4603 my ($PTid, $LibVersion, $Repl) = @_;
4604 my ($MPrefix, $Mangled) = ("", "");
4605 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004606 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004607 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004608 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004609 if(not $BaseType_Name) {
4610 return "";
4611 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004612 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004613 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004614 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4615 while($Suffix=~/(&|\*|const)\Z/)
4616 {
4617 if($Suffix=~s/[ ]*&\Z//) {
4618 $MPrefix .= "R";
4619 }
4620 if($Suffix=~s/[ ]*\*\Z//) {
4621 $MPrefix .= "P";
4622 }
4623 if($Suffix=~s/[ ]*const\Z//)
4624 {
4625 if($MPrefix=~/R|P/
4626 or $Suffix=~/&|\*/) {
4627 $MPrefix .= "K";
4628 }
4629 }
4630 if($Suffix=~s/[ ]*volatile\Z//) {
4631 $MPrefix .= "V";
4632 }
4633 #if($Suffix=~s/[ ]*restrict\Z//) {
4634 #$MPrefix .= "r";
4635 #}
4636 }
4637 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4638 $Mangled .= $Token;
4639 }
4640 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4641 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004642 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004643 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004644 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004645 foreach (@TPos) {
4646 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4647 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004648 }
4649 elsif($TmplParams)
4650 { # remangling mode
4651 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004652 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004653 }
4654 my $MangledNS = "";
4655 my ($SubNS, $SName) = get_sub_ns($ShortName);
4656 if($SubNS) {
4657 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4658 }
4659 $MangledNS .= length($SName).$SName;
4660 if(@TParams) {
4661 add_substitution($MangledNS, $Repl, 0);
4662 }
4663 $Mangled .= "N".$MangledNS;
4664 if(@TParams)
4665 { # templates
4666 $Mangled .= "I";
4667 foreach my $TParam (@TParams) {
4668 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4669 }
4670 $Mangled .= "E";
4671 }
4672 $Mangled .= "E";
4673 }
4674 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4675 {
4676 if($BaseType{"Type"} eq "MethodPtr") {
4677 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4678 }
4679 else {
4680 $Mangled .= "PF";
4681 }
4682 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4683 my @Params = keys(%{$BaseType{"Param"}});
4684 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4685 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4686 }
4687 if(not @Params) {
4688 $Mangled .= "v";
4689 }
4690 $Mangled .= "E";
4691 }
4692 elsif($BaseType{"Type"} eq "FieldPtr")
4693 {
4694 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4695 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4696 }
4697 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4698 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4699 {
4700 if($Mangled eq $Optimized)
4701 {
4702 if($ShortName!~/::/)
4703 { # remove "N ... E"
4704 if($MPrefix) {
4705 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4706 }
4707 else {
4708 $Mangled=~s/\AN(.+)E\Z/$1/g;
4709 }
4710 }
4711 }
4712 else {
4713 $Mangled = $Optimized;
4714 }
4715 }
4716 add_substitution($Mangled, $Repl, 1);
4717 return $Mangled;
4718}
4719
4720sub mangle_template_param($$$)
4721{ # types + literals
4722 my ($TParam, $LibVersion, $Repl) = @_;
4723 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4724 return mangle_param($TPTid, $LibVersion, $Repl);
4725 }
4726 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4727 { # class_name<1u>::method(...)
4728 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4729 }
4730 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4731 { # class_name<(signed char)1>::method(...)
4732 return "L".$IntrinsicMangling{$1}.$2."E";
4733 }
4734 elsif($TParam eq "true")
4735 { # class_name<true>::method(...)
4736 return "Lb1E";
4737 }
4738 elsif($TParam eq "false")
4739 { # class_name<true>::method(...)
4740 return "Lb0E";
4741 }
4742 else { # internal error
4743 return length($TParam).$TParam;
4744 }
4745}
4746
4747sub add_substitution($$$)
4748{
4749 my ($Value, $Repl, $Rec) = @_;
4750 if($Rec)
4751 { # subtypes
4752 my @Subs = ($Value);
4753 while($Value=~s/\A(R|P|K)//) {
4754 push(@Subs, $Value);
4755 }
4756 foreach (reverse(@Subs)) {
4757 add_substitution($_, $Repl, 0);
4758 }
4759 return;
4760 }
4761 return if($Value=~/\AS(\d*)_\Z/);
4762 $Value=~s/\AN(.+)E\Z/$1/g;
4763 return if(defined $Repl->{$Value});
4764 return if(length($Value)<=1);
4765 return if($StdcxxMangling{$Value});
4766 # check for duplicates
4767 my $Base = $Value;
4768 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4769 {
4770 my $Num = $Repl->{$Type};
4771 my $Replace = macro_mangle($Num);
4772 $Base=~s/\Q$Replace\E/$Type/;
4773 }
4774 if(my $OldNum = $Repl->{$Base})
4775 {
4776 $Repl->{$Value} = $OldNum;
4777 return;
4778 }
4779 my @Repls = sort {$b<=>$a} values(%{$Repl});
4780 if(@Repls) {
4781 $Repl->{$Value} = $Repls[0]+1;
4782 }
4783 else {
4784 $Repl->{$Value} = -1;
4785 }
4786 # register duplicates
4787 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004788 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004789 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4790 {
4791 next if($Base eq $Type);
4792 my $Num = $Repl->{$Type};
4793 my $Replace = macro_mangle($Num);
4794 $Base=~s/\Q$Type\E/$Replace/;
4795 $Repl->{$Base} = $Repl->{$Value};
4796 }
4797}
4798
4799sub macro_mangle($)
4800{
4801 my $Num = $_[0];
4802 if($Num==-1) {
4803 return "S_";
4804 }
4805 else
4806 {
4807 my $Code = "";
4808 if($Num<10)
4809 { # S0_, S1_, S2_, ...
4810 $Code = $Num;
4811 }
4812 elsif($Num>=10 and $Num<=35)
4813 { # SA_, SB_, SC_, ...
4814 $Code = chr(55+$Num);
4815 }
4816 else
4817 { # S10_, S11_, S12_
4818 $Code = $Num-26; # 26 is length of english alphabet
4819 }
4820 return "S".$Code."_";
4821 }
4822}
4823
4824sub write_stdcxx_substitution($)
4825{
4826 my $Mangled = $_[0];
4827 if($StdcxxMangling{$Mangled}) {
4828 return $StdcxxMangling{$Mangled};
4829 }
4830 else
4831 {
4832 my @Repls = keys(%StdcxxMangling);
4833 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4834 foreach my $MangledType (@Repls)
4835 {
4836 my $Replace = $StdcxxMangling{$MangledType};
4837 #if($Mangled!~/$Replace/) {
4838 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4839 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4840 #}
4841 }
4842 }
4843 return $Mangled;
4844}
4845
4846sub write_substitution($$)
4847{
4848 my ($Mangled, $Repl) = @_;
4849 if(defined $Repl->{$Mangled}
4850 and my $MnglNum = $Repl->{$Mangled}) {
4851 $Mangled = macro_mangle($MnglNum);
4852 }
4853 else
4854 {
4855 my @Repls = keys(%{$Repl});
4856 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4857 # FIXME: how to apply replacements? by num or by pos
4858 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4859 foreach my $MangledType (@Repls)
4860 {
4861 my $Replace = macro_mangle($Repl->{$MangledType});
4862 if($Mangled!~/$Replace/) {
4863 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4864 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4865 }
4866 }
4867 }
4868 return $Mangled;
4869}
4870
4871sub delete_keywords($)
4872{
4873 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004874 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004875 return $TypeName;
4876}
4877
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004878sub uncover_typedefs($$)
4879{
4880 my ($TypeName, $LibVersion) = @_;
4881 return "" if(not $TypeName);
4882 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4883 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4884 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004885 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004886 while($TypeName_New ne $TypeName_Pre)
4887 {
4888 $TypeName_Pre = $TypeName_New;
4889 my $TypeName_Copy = $TypeName_New;
4890 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004891 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004892 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004893 if(not $Intrinsic_Keywords{$1}) {
4894 $Words{$1} = 1;
4895 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004896 }
4897 foreach my $Word (keys(%Words))
4898 {
4899 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4900 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004901 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004902 if($BaseType_Name=~/\([\*]+\)/)
4903 { # FuncPtr
4904 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4905 {
4906 my $Type_Suffix = $1;
4907 $TypeName_New = $BaseType_Name;
4908 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004909 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004910 }
4911 }
4912 }
4913 else
4914 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004915 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004916 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004917 }
4918 }
4919 }
4920 }
4921 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4922}
4923
4924sub isInternal($)
4925{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004926 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4927 {
4928 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4929 {
4930 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4931 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4932 return 1;
4933 }
4934 }
4935 }
4936 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004937}
4938
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004939sub getDataVal($$)
4940{
4941 my ($InfoId, $TypeId) = @_;
4942 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4943 {
4944 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4945 {
4946 if(defined $LibInfo{$Version}{"info_type"}{$1}
4947 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004948 {
4949 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004950 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004951 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4952 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004953 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004954 if(my $Addr = getTreeAttr_Op($1)) {
4955 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004956 }
4957 }
4958 }
4959 }
4960 else {
4961 return getInitVal($1, $TypeId);
4962 }
4963 }
4964 }
4965 return undef;
4966}
4967
4968sub getInitVal($$)
4969{
4970 my ($InfoId, $TypeId) = @_;
4971 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4972 {
4973 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4974 {
4975 if($InfoType eq "integer_cst")
4976 {
4977 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004978 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004979 { # characters
4980 $Val = chr($Val);
4981 }
4982 return $Val;
4983 }
4984 elsif($InfoType eq "string_cst") {
4985 return getNodeStrCst($InfoId);
4986 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004987 elsif($InfoType eq "var_decl")
4988 {
4989 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4990 return $Name;
4991 }
4992 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004993 }
4994 }
4995 return undef;
4996}
4997
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004998sub set_Class_And_Namespace($)
4999{
5000 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005001 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005002 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005003 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005004 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005005 my $NSInfoId = $1;
5006 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
5007 {
5008 if($InfoType eq "namespace_decl") {
5009 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
5010 }
5011 elsif($InfoType eq "record_type") {
5012 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
5013 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005014 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005015 }
5016 }
5017 if($SymbolInfo{$Version}{$InfoId}{"Class"}
5018 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005019 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005020 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005021 { # skip
5022 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005024 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005025
5026 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005027}
5028
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005029sub debugMangling($)
5030{
5031 my $LibVersion = $_[0];
5032 my %Mangled = ();
5033 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
5034 {
5035 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
5036 {
5037 if($Mngl=~/\A(_Z|\?)/) {
5038 $Mangled{$Mngl}=$InfoId;
5039 }
5040 }
5041 }
5042 translateSymbols(keys(%Mangled), $LibVersion);
5043 foreach my $Mngl (keys(%Mangled))
5044 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005045 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
5046 my $U2 = $tr_name{$Mngl};
5047 if($U1 ne $U2) {
5048 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005049 }
5050 }
5051}
5052
5053sub linkSymbol($)
5054{ # link symbols from shared libraries
5055 # with the symbols from header files
5056 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005057 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005058 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005059 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5060 or $EMERGENCY_MODE_48)
5061 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
5062 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
5063 # GCC 4.8 doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005064 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005065 {
5066 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
5067 return correct_incharge($InfoId, $Version, $Mangled);
5068 }
5069 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005070 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005071 or not $BinaryOnly
5072 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005073 { # 1. --headers-only mode
5074 # 2. not mangled src-only symbols
5075 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
5076 return $Mangled;
5077 }
5078 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005079 }
5080 return "";
5081}
5082
5083sub setLanguage($$)
5084{
5085 my ($LibVersion, $Lang) = @_;
5086 if(not $UserLang) {
5087 $COMMON_LANGUAGE{$LibVersion} = $Lang;
5088 }
5089}
5090
5091sub getSymbolInfo($)
5092{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005093 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005094 if(isInternal($InfoId)) {
5095 return;
5096 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005097 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5098 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005099 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5100 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005101 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005102 return;
5103 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005104 setFuncAccess($InfoId);
5105 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005106 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5107 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005108 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005109 return;
5110 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005111
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005112 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005113 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005114 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005115 if(not defined $TypeInfo{$Version}{$Return}
5116 or not $TypeInfo{$Version}{$Return}{"Name"})
5117 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005118 delete($SymbolInfo{$Version}{$InfoId});
5119 return;
5120 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005121 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005122 }
5123 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5124 {
5125 if(defined $MissedTypedef{$Version}{$Rid})
5126 {
5127 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5128 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5129 }
5130 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005131 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005132 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5133 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005134 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005135 my $Orig = getFuncOrig($InfoId);
5136 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005137 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5138 {
5139 delete($SymbolInfo{$Version}{$InfoId});
5140 return;
5141 }
5142
5143 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005144 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005145 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005146 return;
5147 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005148
5149 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005150 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005151 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5152
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005153 my @TParams = getTParams($Orig, "Func");
5154 if(not @TParams)
5155 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005156 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005157 return;
5158 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005159 foreach my $Pos (0 .. $#TParams)
5160 {
5161 my $Val = $TParams[$Pos];
5162 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5163
5164 if($Tmpl)
5165 {
5166 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5167 {
5168 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5169 }
5170 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005171 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005172
5173 if($Tmpl)
5174 {
5175 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5176 {
5177 if($Pos>$#TParams)
5178 {
5179 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5180 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5181 }
5182 }
5183 }
5184
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005185 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5186 { # operator<< <T>, operator>> <T>
5187 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5188 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005189 if(@TParams) {
5190 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5191 }
5192 else {
5193 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5194 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005195 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005196 }
5197 else
5198 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005199 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005200 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005201 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5202 {
5203 if($OSgroup eq "windows")
5204 { # cut the offset
5205 $MnglName=~s/\@\d+\Z//g;
5206 }
5207 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5208
5209 # NOTE: mangling of some symbols may change depending on GCC version
5210 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5211 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5212 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005213
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005214 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005215 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005216 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005217 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005218 return;
5219 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005220 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005221 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005222 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005223 if($Skip)
5224 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005225 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005226 return;
5227 }
5228 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005229 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5230 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5231 }
5232
5233 if(set_Class_And_Namespace($InfoId))
5234 {
5235 delete($SymbolInfo{$Version}{$InfoId});
5236 return;
5237 }
5238
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005239 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5240 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005241 if(not defined $TypeInfo{$Version}{$ClassId}
5242 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5243 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005244 delete($SymbolInfo{$Version}{$InfoId});
5245 return;
5246 }
5247 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005248 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5249 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005250 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005251 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005252 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005253 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005254 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005255 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005256 }
5257 if($COMMON_LANGUAGE{$Version} eq "C++")
5258 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005259 # C++ or --headers-only mode
5260 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005261 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005262 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5263 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005264 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005265 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005266 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005267 if(my $Mangled = linkSymbol($InfoId)) {
5268 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005269 }
5270 }
5271 if($OStarget eq "windows")
5272 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005273 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005274 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005275 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005276 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005277 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005278 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005279 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005280 }
5281 }
5282 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005283 else
5284 { # not mangled in C
5285 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5286 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005287 if(not $CheckHeadersOnly
5288 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5289 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5290 {
5291 my $Incorrect = 0;
5292
5293 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5294 {
5295 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5296 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5297 { # mangled in the TU dump, but not mangled in the library
5298 $Incorrect = 1;
5299 }
5300 }
5301 else
5302 {
5303 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5304 { # all C++ functions are not mangled in the TU dump
5305 $Incorrect = 1;
5306 }
5307 }
5308 if($Incorrect)
5309 {
5310 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5311 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5312 }
5313 }
5314 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005315 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005316 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005317 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005318 return;
5319 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005320 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005321 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005322 { # identify virtual and pure virtual functions
5323 # NOTE: constructors cannot be virtual
5324 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5325 # in the TU dump, so taking it from the original symbol
5326 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5327 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5328 { # NOTE: D2 destructors are not present in a v-table
5329 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5330 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005331 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005332 if(isInline($InfoId)) {
5333 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005334 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005335 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005336 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5337 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005338 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5339 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005340 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005341 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005342 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005343 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005344 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005345 }
5346 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005347 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5348 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005349 if(not $ExtraDump)
5350 {
5351 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5352 { # non-target symbols
5353 delete($SymbolInfo{$Version}{$InfoId});
5354 return;
5355 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005356 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005357 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005358 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5359 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5360 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5361 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005362 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005363 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5364 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005365 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005366 return;
5367 }
5368 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005369 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005370 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005371 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005372 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005373 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005374 return;
5375 }
5376 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005377 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005378 }
5379 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005380 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5381 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5382 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005383 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005384 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5385 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005386 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005387 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005388 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005389 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005390 }
5391 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005392 if(getFuncLink($InfoId) eq "Static") {
5393 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005394 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005395 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5396 {
5397 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5398 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005399 if($Unmangled=~/\.\_\d/)
5400 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005401 delete($SymbolInfo{$Version}{$InfoId});
5402 return;
5403 }
5404 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005405 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005406
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005407 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5408 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005409 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005410 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5411 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005412 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005413
5414 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5415 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5416 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005417
5418 if($ExtraDump) {
5419 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5420 }
5421}
5422
5423sub guessHeader($)
5424{
5425 my $InfoId = $_[0];
5426 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5427 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5428 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5429 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5430 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5431 {
5432 if(get_filename($HPath) eq $Header)
5433 {
5434 my $HDir = get_filename(get_dirname($HPath));
5435 if($HDir ne "include"
5436 and $HDir=~/\A[a-z]+\Z/i) {
5437 return join_P($HDir, $Header);
5438 }
5439 }
5440 }
5441 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005442}
5443
5444sub isInline($)
5445{ # "body: undefined" in the tree
5446 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005447 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5448 {
5449 if($Info=~/ undefined /i) {
5450 return 0;
5451 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005452 }
5453 return 1;
5454}
5455
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005456sub hasThrow($)
5457{
5458 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5459 {
5460 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5461 return getTreeAttr_Unql($1, "unql");
5462 }
5463 }
5464 return 1;
5465}
5466
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005467sub getTypeId($)
5468{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005469 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5470 {
5471 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5472 return $1;
5473 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005474 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005475 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005476}
5477
5478sub setTypeMemb($$)
5479{
5480 my ($TypeId, $TypeAttr) = @_;
5481 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005482 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005483 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005484 if($TypeType eq "Enum")
5485 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005486 my $MInfoId = getTreeAttr_Csts($TypeId);
5487 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005488 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005489 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5490 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005491 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005492 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5493 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005494 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005495 }
5496 }
5497 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5498 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005499 my $MInfoId = getTreeAttr_Flds($TypeId);
5500 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005501 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005502 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5503 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005504 if(not $IType or $IType ne "field_decl")
5505 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005506
5507 if($IType eq "var_decl")
5508 { # static field
5509 $StaticFields = 1;
5510 }
5511
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005512 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005513 next;
5514 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005515 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005516 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005517 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005518 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005519 }
5520 if(not $StructMembName)
5521 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005522 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005523 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005524 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005525 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5526 if(isAnon($UnnamedTName))
5527 { # rename unnamed fields to unnamed0, unnamed1, ...
5528 $StructMembName = "unnamed".($UnnamedPos++);
5529 }
5530 }
5531 }
5532 if(not $StructMembName)
5533 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005534 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005535 next;
5536 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005537 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005538 if(defined $MissedTypedef{$Version}{$MembTypeId})
5539 {
5540 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5541 $MembTypeId = $AddedTid;
5542 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005543 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005544
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005545 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5546 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005547 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005548 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005549 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5550 }
5551 if($MInfo=~/spec:\s*mutable /)
5552 { # mutable fields
5553 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005554 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005555 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005556 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5557 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005558 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005559 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005560 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005561 }
5562 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005563 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005564 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5565 { # template
5566 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5567 }
5568 else {
5569 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5570 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005571 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005572
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005573 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005574 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005575 }
5576 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005577
5578 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005579}
5580
5581sub setFuncParams($)
5582{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005583 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005584 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005585
5586 my $FType = getFuncType($InfoId);
5587
5588 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005589 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005590 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5591 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005592 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005593 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005594 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5595 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005596 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005597 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5598 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005599 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005600 else
5601 { # skip
5602 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005603 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005604 # skip "this"-parameter
5605 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005606 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005607 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005608 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005609 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005610 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5611 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5612 if(not $ParamName)
5613 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005614 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005615 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005616 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5617 {
5618 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5619 $ParamTypeId = $AddedTid;
5620 }
5621 }
5622 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005623 if(not $PType or $PType eq "Unknown") {
5624 return 1;
5625 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005626 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005627 if(not $PTName) {
5628 return 1;
5629 }
5630 if($PTName eq "void") {
5631 last;
5632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005633 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005634 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005635 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005636 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005637 $ParamInfoId = getNextElem($ParamInfoId);
5638 next;
5639 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005640 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005641
5642 if(my %Base = get_BaseType($ParamTypeId, $Version))
5643 {
5644 if(defined $Base{"Template"}) {
5645 return 1;
5646 }
5647 }
5648
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005649 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005650 if(my $Algn = getAlgn($ParamInfoId)) {
5651 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5652 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005653 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5654 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005655 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005656 }
5657 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005658 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005659 if($ParamName ne "this" or $FType ne "Method") {
5660 $PPos += 1;
5661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005662 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005663 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005664 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005665 }
5666 return 0;
5667}
5668
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005669sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005670{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005671 my ($InfoId, $Vtt_Pos) = @_;
5672 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005673 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005674 my $FType = getFuncType($InfoId);
5675
5676 if($FType eq "Method")
5677 {
5678 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005679 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005680 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005681 if(not $ParamListElemId)
5682 { # foo(...)
5683 return 1;
5684 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005685 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005686 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005687 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005688 { # actual params: may differ from formal args
5689 # formal int*const
5690 # actual: int*
5691 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005692 {
5693 $Vtt_Pos=-1;
5694 $ParamListElemId = getNextElem($ParamListElemId);
5695 next;
5696 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005697 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5698 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005699 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005700 $HaveVoid = 1;
5701 last;
5702 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005703 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005704 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005705 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5706 {
5707 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5708 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5709 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005710 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005711 }
5712 }
5713 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5714 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005715 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005716 { # params
5717 if($OldId ne $ParamTypeId)
5718 {
5719 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5720 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5721
5722 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5723 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5724 }
5725 }
5726 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005727 }
5728 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005729 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005730 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005731 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5732 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005733 if($PurpType eq "nop_expr")
5734 { # func ( const char* arg = (const char*)(void*)0 )
5735 $PurpId = getTreeAttr_Op($PurpId);
5736 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005737 my $Val = getInitVal($PurpId, $ParamTypeId);
5738 if(defined $Val) {
5739 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5740 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005741 }
5742 }
5743 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005744 if($Pos!=0 or $FType ne "Method") {
5745 $PPos += 1;
5746 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005747 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005748 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005749 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005750}
5751
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005752sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005753{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005754 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5755 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005756 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5757 return $1;
5758 }
5759 }
5760 return "";
5761}
5762
5763sub getTreeAttr_Chain($)
5764{
5765 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5766 {
5767 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5768 return $1;
5769 }
5770 }
5771 return "";
5772}
5773
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005774sub getTreeAttr_Unql($)
5775{
5776 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5777 {
5778 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5779 return $1;
5780 }
5781 }
5782 return "";
5783}
5784
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005785sub getTreeAttr_Scpe($)
5786{
5787 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5788 {
5789 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5790 return $1;
5791 }
5792 }
5793 return "";
5794}
5795
5796sub getTreeAttr_Type($)
5797{
5798 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5799 {
5800 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5801 return $1;
5802 }
5803 }
5804 return "";
5805}
5806
5807sub getTreeAttr_Name($)
5808{
5809 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5810 {
5811 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5812 return $1;
5813 }
5814 }
5815 return "";
5816}
5817
5818sub getTreeAttr_Mngl($)
5819{
5820 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5821 {
5822 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5823 return $1;
5824 }
5825 }
5826 return "";
5827}
5828
5829sub getTreeAttr_Prms($)
5830{
5831 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5832 {
5833 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5834 return $1;
5835 }
5836 }
5837 return "";
5838}
5839
5840sub getTreeAttr_Fncs($)
5841{
5842 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5843 {
5844 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5845 return $1;
5846 }
5847 }
5848 return "";
5849}
5850
5851sub getTreeAttr_Csts($)
5852{
5853 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5854 {
5855 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5856 return $1;
5857 }
5858 }
5859 return "";
5860}
5861
5862sub getTreeAttr_Purp($)
5863{
5864 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5865 {
5866 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5867 return $1;
5868 }
5869 }
5870 return "";
5871}
5872
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005873sub getTreeAttr_Op($)
5874{
5875 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5876 {
5877 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5878 return $1;
5879 }
5880 }
5881 return "";
5882}
5883
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005884sub getTreeAttr_Valu($)
5885{
5886 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5887 {
5888 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5889 return $1;
5890 }
5891 }
5892 return "";
5893}
5894
5895sub getTreeAttr_Flds($)
5896{
5897 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5898 {
5899 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5900 return $1;
5901 }
5902 }
5903 return "";
5904}
5905
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005906sub getTreeAttr_Binf($)
5907{
5908 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5909 {
5910 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5911 return $1;
5912 }
5913 }
5914 return "";
5915}
5916
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005917sub getTreeAttr_Args($)
5918{
5919 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5920 {
5921 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005922 return $1;
5923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005924 }
5925 return "";
5926}
5927
5928sub getTreeValue($)
5929{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005930 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5931 {
5932 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5933 return $1;
5934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005935 }
5936 return "";
5937}
5938
5939sub getTreeAccess($)
5940{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005941 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005942 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005943 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5944 {
5945 my $Access = $1;
5946 if($Access eq "prot") {
5947 return "protected";
5948 }
5949 elsif($Access eq "priv") {
5950 return "private";
5951 }
5952 }
5953 elsif($Info=~/ protected /)
5954 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005955 return "protected";
5956 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005957 elsif($Info=~/ private /)
5958 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005959 return "private";
5960 }
5961 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005962 return "public";
5963}
5964
5965sub setFuncAccess($)
5966{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005967 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005968 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005969 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005970 }
5971 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005972 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005973 }
5974}
5975
5976sub setTypeAccess($$)
5977{
5978 my ($TypeId, $TypeAttr) = @_;
5979 my $Access = getTreeAccess($TypeId);
5980 if($Access eq "protected") {
5981 $TypeAttr->{"Protected"} = 1;
5982 }
5983 elsif($Access eq "private") {
5984 $TypeAttr->{"Private"} = 1;
5985 }
5986}
5987
5988sub setFuncKind($)
5989{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005990 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5991 {
5992 if($Info=~/pseudo tmpl/) {
5993 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5994 }
5995 elsif($Info=~/ constructor /) {
5996 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5997 }
5998 elsif($Info=~/ destructor /) {
5999 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
6000 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006001 }
6002}
6003
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006004sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006005{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006006 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6007 {
6008 if($Info=~/spec[ ]*:[ ]*pure /) {
6009 return "PureVirt";
6010 }
6011 elsif($Info=~/spec[ ]*:[ ]*virt /) {
6012 return "Virt";
6013 }
6014 elsif($Info=~/ pure\s+virtual /)
6015 { # support for old GCC versions
6016 return "PureVirt";
6017 }
6018 elsif($Info=~/ virtual /)
6019 { # support for old GCC versions
6020 return "Virt";
6021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006022 }
6023 return "";
6024}
6025
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006026sub getFuncLink($)
6027{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006028 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6029 {
6030 if($Info=~/link[ ]*:[ ]*static /) {
6031 return "Static";
6032 }
6033 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006034 return $1;
6035 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006036 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006037 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006038}
6039
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006040sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006041{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006042 my ($Symbol, $LibVersion) = @_;
6043 return "" if(not $Symbol or not $LibVersion);
6044 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
6045 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006046 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006047 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
6048 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
6049 }
6050 }
6051 if($NS)
6052 {
6053 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6054 return $NS;
6055 }
6056 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006057 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006058 while($NS=~s/::[^:]+\Z//)
6059 {
6060 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6061 return $NS;
6062 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006063 }
6064 }
6065 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006066
6067 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006068}
6069
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006070sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006071{
6072 my ($TypeName, $LibVersion) = @_;
6073 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006074 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006075 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006076 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6077 return $NS;
6078 }
6079 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006080 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006081 while($NS=~s/::[^:]+\Z//)
6082 {
6083 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6084 return $NS;
6085 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006086 }
6087 }
6088 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006089 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006090}
6091
6092sub getNameSpace($)
6093{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006094 my $InfoId = $_[0];
6095 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006096 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006097 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006098 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006099 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006100 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006101 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6102 {
6103 my $NameSpace = getTreeStr($1);
6104 if($NameSpace eq "::")
6105 { # global namespace
6106 return "";
6107 }
6108 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6109 $NameSpace = $BaseNameSpace."::".$NameSpace;
6110 }
6111 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6112 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006113 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006114 else {
6115 return "";
6116 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006117 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006118 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006119 { # inside data type
6120 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6121 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006123 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006124 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006125 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006126}
6127
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006128sub getEnumMembVal($)
6129{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006130 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006131 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006132 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6133 {
6134 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6135 {
6136 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6137 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6138 return getTreeValue($1);
6139 }
6140 else
6141 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6142 return getTreeValue($1);
6143 }
6144 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006145 }
6146 }
6147 return "";
6148}
6149
6150sub getSize($)
6151{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006152 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6153 {
6154 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6155 return getTreeValue($1);
6156 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006157 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006158 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006159}
6160
6161sub getAlgn($)
6162{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006163 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6164 {
6165 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6166 return $1;
6167 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006168 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006169 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006170}
6171
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006172sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006173{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006174 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6175 {
6176 if($Info=~/ bitfield /) {
6177 return getSize($_[0]);
6178 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006179 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006180 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006181}
6182
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006183sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006184{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006185 if(my $Chan = getTreeAttr_Chan($_[0])) {
6186 return $Chan;
6187 }
6188 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6189 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006190 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006191 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006192}
6193
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006194sub registerHeader($$)
6195{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006196 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006197 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006198 return "";
6199 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006200 if(is_abs($Header) and not -f $Header)
6201 { # incorrect absolute path
6202 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006203 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006204 if(skipHeader($Header, $LibVersion))
6205 { # skip
6206 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006207 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006208 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6209 {
6210 detect_header_includes($Header_Path, $LibVersion);
6211
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006212 if(defined $Tolerance and $Tolerance=~/3/)
6213 { # 3 - skip headers that include non-Linux headers
6214 if($OSgroup ne "windows")
6215 {
6216 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6217 {
6218 if(specificHeader($Inc, "windows")) {
6219 return "";
6220 }
6221 }
6222 }
6223 }
6224
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006225 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6226 { # redirect
6227 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6228 or skipHeader($RHeader_Path, $LibVersion))
6229 { # skip
6230 return "";
6231 }
6232 $Header_Path = $RHeader_Path;
6233 }
6234 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6235 { # skip
6236 return "";
6237 }
6238
6239 if(my $HName = get_filename($Header_Path))
6240 { # register
6241 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6242 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6243 }
6244
6245 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6246 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006247 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006248 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006249 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006250 }
6251
6252 if($CheckHeadersOnly
6253 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6254 { # /usr/include/c++/4.6.1/...
6255 $STDCXX_TESTING = 1;
6256 }
6257
6258 return $Header_Path;
6259 }
6260 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006261}
6262
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006263sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006264{
6265 my ($Dir, $WithDeps, $LibVersion) = @_;
6266 $Dir=~s/[\/\\]+\Z//g;
6267 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006268 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006269
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006270 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006271 if($WithDeps)
6272 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006273 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6274 return;
6275 }
6276 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6277 $Mode = "DepsOnly";
6278 }
6279 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006280 else
6281 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006282 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6283 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6284 return;
6285 }
6286 }
6287 $Header_Dependency{$LibVersion}{$Dir} = 1;
6288 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6289 if($Mode eq "DepsOnly")
6290 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006291 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006292 $Header_Dependency{$LibVersion}{$Path} = 1;
6293 }
6294 return;
6295 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006296 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006297 {
6298 if($WithDeps)
6299 {
6300 my $SubDir = $Path;
6301 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6302 { # register all sub directories
6303 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6304 }
6305 }
6306 next if(is_not_header($Path));
6307 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006308 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006309 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006310 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6311 }
6312 }
6313 if(get_filename($Dir) eq "include")
6314 { # search for "lib/include/" directory
6315 my $LibDir = $Dir;
6316 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006317 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006318 }
6319 }
6320}
6321
6322sub parse_redirect($$$)
6323{
6324 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006325 my @Errors = ();
6326 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6327 push(@Errors, $1);
6328 }
6329 my $Redirect = "";
6330 foreach (@Errors)
6331 {
6332 s/\s{2,}/ /g;
6333 if(/(only|must\ include
6334 |update\ to\ include
6335 |replaced\ with
6336 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006337 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006338 {
6339 $Redirect = $2;
6340 last;
6341 }
6342 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6343 {
6344 $Redirect = $2;
6345 last;
6346 }
6347 elsif(/this\ header\ should\ not\ be\ used
6348 |programs\ should\ not\ directly\ include
6349 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6350 |is\ not\ supported\ API\ for\ general\ use
6351 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006352 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006353 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6354 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6355 }
6356 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006357 if($Redirect)
6358 {
6359 $Redirect=~s/\A<//g;
6360 $Redirect=~s/>\Z//g;
6361 }
6362 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006363}
6364
6365sub parse_includes($$)
6366{
6367 my ($Content, $Path) = @_;
6368 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006369 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006370 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006371 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006372 my $Method = substr($Header, 0, 1, "");
6373 substr($Header, length($Header)-1, 1, "");
6374 $Header = path_format($Header, $OSgroup);
6375 if($Method eq "\"" or is_abs($Header))
6376 {
6377 if(-e join_P(get_dirname($Path), $Header))
6378 { # relative path exists
6379 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006380 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006381 else
6382 { # include "..." that doesn't exist is equal to include <...>
6383 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006384 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006385 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006386 else {
6387 $Includes{$Header} = 1;
6388 }
6389 }
6390 if($ExtraInfo)
6391 {
6392 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6393 { # FT_FREETYPE_H
6394 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006395 }
6396 }
6397 return \%Includes;
6398}
6399
6400sub ignore_path($)
6401{
6402 my $Path = $_[0];
6403 if($Path=~/\~\Z/)
6404 {# skipping system backup files
6405 return 1;
6406 }
6407 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6408 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6409 return 1;
6410 }
6411 return 0;
6412}
6413
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006414sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006415{
6416 my ($ArrRef, $W) = @_;
6417 return if(length($W)<2);
6418 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6419}
6420
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006421sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006422{
6423 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006424
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006425 $H1=~s/\.[a-z]+\Z//ig;
6426 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006427
6428 my $Hname1 = get_filename($H1);
6429 my $Hname2 = get_filename($H2);
6430 my $HDir1 = get_dirname($H1);
6431 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006432 my $Dirname1 = get_filename($HDir1);
6433 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006434
6435 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6436 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6437
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006438 if($_[0] eq $_[1]
6439 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006440 return 0;
6441 }
6442 elsif($H1=~/\A\Q$H2\E/) {
6443 return 1;
6444 }
6445 elsif($H2=~/\A\Q$H1\E/) {
6446 return -1;
6447 }
6448 elsif($HDir1=~/\Q$Hname1\E/i
6449 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006450 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006451 return -1;
6452 }
6453 elsif($HDir2=~/\Q$Hname2\E/i
6454 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006455 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006456 return 1;
6457 }
6458 elsif($Hname1=~/\Q$Dirname1\E/i
6459 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006460 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006461 return -1;
6462 }
6463 elsif($Hname2=~/\Q$Dirname2\E/i
6464 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006465 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006466 return 1;
6467 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006468 elsif($Hname1=~/(config|lib|util)/i
6469 and $Hname2!~/(config|lib|util)/i)
6470 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006471 return -1;
6472 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006473 elsif($Hname2=~/(config|lib|util)/i
6474 and $Hname1!~/(config|lib|util)/i)
6475 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006476 return 1;
6477 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006478 else
6479 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006480 my $R1 = checkRelevance($H1);
6481 my $R2 = checkRelevance($H2);
6482 if($R1 and not $R2)
6483 { # libebook/e-book.h
6484 return -1;
6485 }
6486 elsif($R2 and not $R1)
6487 { # libebook/e-book.h
6488 return 1;
6489 }
6490 else
6491 {
6492 return (lc($H1) cmp lc($H2));
6493 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006494 }
6495}
6496
6497sub searchForHeaders($)
6498{
6499 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006500
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006501 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006502 registerGccHeaders();
6503
6504 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6505 { # c++ standard include paths
6506 registerCppHeaders();
6507 }
6508
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006509 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006510 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6511 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006512 {
6513 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006514 if($SystemRoot)
6515 {
6516 if(is_abs($Path)) {
6517 $Path = $SystemRoot.$Path;
6518 }
6519 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006520 if(not -e $Path) {
6521 exitStatus("Access_Error", "can't access \'$Path\'");
6522 }
6523 elsif(-f $Path) {
6524 exitStatus("Access_Error", "\'$Path\' - not a directory");
6525 }
6526 elsif(-d $Path)
6527 {
6528 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006529 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006530 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6531 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006532 }
6533 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006534 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006535 }
6536 }
6537 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006538 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006539 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6540 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006541
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006542 # registering directories
6543 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6544 {
6545 next if(not -e $Path);
6546 $Path = get_abs_path($Path);
6547 $Path = path_format($Path, $OSgroup);
6548 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006549 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006550 }
6551 elsif(-f $Path)
6552 {
6553 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006554 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006555 and not $LocalIncludes{$Dir})
6556 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006557 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006558 # if(my $OutDir = get_dirname($Dir))
6559 # { # registering the outer directory
6560 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6561 # and not $LocalIncludes{$OutDir}) {
6562 # registerDir($OutDir, 0, $LibVersion);
6563 # }
6564 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006565 }
6566 }
6567 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006568
6569 # clean memory
6570 %RegisteredDirs = ();
6571
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006572 # registering headers
6573 my $Position = 0;
6574 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6575 {
6576 if(is_abs($Dest) and not -e $Dest) {
6577 exitStatus("Access_Error", "can't access \'$Dest\'");
6578 }
6579 $Dest = path_format($Dest, $OSgroup);
6580 if(is_header($Dest, 1, $LibVersion))
6581 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006582 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006583 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6584 }
6585 }
6586 elsif(-d $Dest)
6587 {
6588 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006589 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006590 {
6591 next if(ignore_path($Path));
6592 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006593 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006594 push(@Registered, $HPath);
6595 }
6596 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006597 @Registered = sort {sortHeaders($a, $b)} @Registered;
6598 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006599 foreach my $Path (@Registered) {
6600 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6601 }
6602 }
6603 else {
6604 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6605 }
6606 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006607
6608 if(defined $Tolerance and $Tolerance=~/4/)
6609 { # 4 - skip headers included by others
6610 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6611 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006612 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006613 delete($Registered_Headers{$LibVersion}{$Path});
6614 }
6615 }
6616 }
6617
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006618 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6619 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006620 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006621 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006622 if(is_abs($Header) and not -f $Header) {
6623 exitStatus("Access_Error", "can't access file \'$Header\'");
6624 }
6625 $Header = path_format($Header, $OSgroup);
6626 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6627 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006628 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006629 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006630 }
6631 else {
6632 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6633 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006634 }
6635 }
6636 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6637 { # set relative paths (for duplicates)
6638 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6639 { # search for duplicates
6640 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6641 my $Prefix = get_dirname($FirstPath);
6642 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6643 { # detect a shortest distinguishing prefix
6644 my $NewPrefix = $1;
6645 my %Identity = ();
6646 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6647 {
6648 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6649 $Identity{$Path} = $1;
6650 }
6651 }
6652 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6653 { # all names are differend with current prefix
6654 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6655 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6656 }
6657 last;
6658 }
6659 $Prefix = $NewPrefix; # increase prefix
6660 }
6661 }
6662 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006663
6664 # clean memory
6665 %HeaderName_Paths = ();
6666
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006667 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6668 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006669 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006670 my ($Pos, $PairPos) = (-1, -1);
6671 my ($Path, $PairPath) = ();
6672 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6673 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6674 foreach my $Header_Path (@Paths)
6675 {
6676 if(get_filename($Header_Path) eq $PairName)
6677 {
6678 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6679 $PairPath = $Header_Path;
6680 }
6681 if(get_filename($Header_Path) eq $HeaderName)
6682 {
6683 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6684 $Path = $Header_Path;
6685 }
6686 }
6687 if($PairPos!=-1 and $Pos!=-1
6688 and int($PairPos)<int($Pos))
6689 {
6690 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6691 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6692 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6693 }
6694 }
6695 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6696 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6697 }
6698}
6699
6700sub detect_real_includes($$)
6701{
6702 my ($AbsPath, $LibVersion) = @_;
6703 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6704 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6705 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6706 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6707 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006708 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6709
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006710 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6711 return () if(not $Path);
6712 open(PREPROC, $Path);
6713 while(<PREPROC>)
6714 {
6715 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6716 {
6717 my $Include = path_format($1, $OSgroup);
6718 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6719 next;
6720 }
6721 if($Include eq $AbsPath) {
6722 next;
6723 }
6724 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6725 }
6726 }
6727 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006728 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6729}
6730
6731sub detect_header_includes($$)
6732{
6733 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006734 return if(not $LibVersion or not $Path);
6735 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6736 return;
6737 }
6738 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6739
6740 if(not -e $Path) {
6741 return;
6742 }
6743
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006744 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006745 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6746 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006747 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006748 {
6749 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006750 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006751 }
6752 if($RedirectPath ne $Path) {
6753 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6754 }
6755 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006756 else
6757 { # can't find
6758 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6759 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006760 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006761 if(my $Inc = parse_includes($Content, $Path))
6762 {
6763 foreach my $Include (keys(%{$Inc}))
6764 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006765 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006766
6767 if(defined $Tolerance and $Tolerance=~/4/)
6768 {
6769 if(my $HPath = identifyHeader($Include, $LibVersion))
6770 {
6771 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6772 }
6773 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006775 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006776}
6777
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006778sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006779{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006780 my $Path = $_[0];
6781 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006782 if($OStarget eq "symbian")
6783 {
6784 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6785 { # epoc32/include/libc/{stdio, ...}.h
6786 return 1;
6787 }
6788 }
6789 else
6790 {
6791 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6792 { # /usr/include/{stdio, ...}.h
6793 return 1;
6794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006796 return 0;
6797}
6798
6799sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006800{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006801 my $Dir = $_[0];
6802 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006803 if($OStarget eq "symbian")
6804 {
6805 if(get_filename($OutDir) eq "libc"
6806 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6807 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6808 return 1;
6809 }
6810 }
6811 else
6812 { # linux
6813 if($OutDir eq "/usr/include"
6814 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6815 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6816 return 1;
6817 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006818 }
6819 return 0;
6820}
6821
6822sub detect_recursive_includes($$)
6823{
6824 my ($AbsPath, $LibVersion) = @_;
6825 return () if(not $AbsPath);
6826 if(isCyclical(\@RecurInclude, $AbsPath)) {
6827 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6828 }
6829 my ($AbsDir, $Name) = separate_path($AbsPath);
6830 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006831 { # system GLIBC internals
6832 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006833 }
6834 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6835 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6836 }
6837 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006838
6839 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6840 { # skip /usr/include/c++/*/ headers
6841 return () if(not $ExtraInfo);
6842 }
6843
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006844 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006845 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006846 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006847 { # check "real" (non-"model") include paths
6848 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6849 pop(@RecurInclude);
6850 return @Paths;
6851 }
6852 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6853 detect_header_includes($AbsPath, $LibVersion);
6854 }
6855 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6856 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006857 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006858 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006859 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006860 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006861 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006862 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006863 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006864 }
6865 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006866 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006867 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006868 { # search for the nearest header
6869 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006870 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006871 if(-f $Candidate) {
6872 $HPath = $Candidate;
6873 }
6874 }
6875 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006876 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006877 }
6878 next if(not $HPath);
6879 if($HPath eq $AbsPath) {
6880 next;
6881 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006882
6883 if($Debug)
6884 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006885# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6886# {
6887# print STDERR "$AbsPath -> $HPath\n";
6888# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006889 }
6890
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006891 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6892 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006893 { # only include <...>, skip include "..." prefixes
6894 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6895 }
6896 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6897 {
6898 if($IncPath eq $AbsPath) {
6899 next;
6900 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006901 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6902 if($RIncType==-1)
6903 { # include "..."
6904 $RIncType = $IncType;
6905 }
6906 elsif($RIncType==2)
6907 {
6908 if($IncType!=-1) {
6909 $RIncType = $IncType;
6910 }
6911 }
6912 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006913 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6914 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6915 }
6916 }
6917 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6918 {
6919 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6920 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6921 { # distinguish math.h from glibc and math.h from the tested library
6922 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6923 last;
6924 }
6925 }
6926 }
6927 pop(@RecurInclude);
6928 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6929}
6930
6931sub find_in_framework($$$)
6932{
6933 my ($Header, $Framework, $LibVersion) = @_;
6934 return "" if(not $Header or not $Framework or not $LibVersion);
6935 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6936 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6937 }
6938 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6939 {
6940 if(get_filename($Dependency) eq $Framework
6941 and -f get_dirname($Dependency)."/".$Header) {
6942 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6943 }
6944 }
6945 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6946}
6947
6948sub find_in_defaults($)
6949{
6950 my $Header = $_[0];
6951 return "" if(not $Header);
6952 if(defined $Cache{"find_in_defaults"}{$Header}) {
6953 return $Cache{"find_in_defaults"}{$Header};
6954 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006955 foreach my $Dir (@DefaultIncPaths,
6956 @DefaultGccPaths,
6957 @DefaultCppPaths,
6958 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006959 {
6960 next if(not $Dir);
6961 if(-f $Dir."/".$Header) {
6962 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6963 }
6964 }
6965 return ($Cache{"find_in_defaults"}{$Header}="");
6966}
6967
6968sub cmp_paths($$)
6969{
6970 my ($Path1, $Path2) = @_;
6971 my @Parts1 = split(/[\/\\]/, $Path1);
6972 my @Parts2 = split(/[\/\\]/, $Path2);
6973 foreach my $Num (0 .. $#Parts1)
6974 {
6975 my $Part1 = $Parts1[$Num];
6976 my $Part2 = $Parts2[$Num];
6977 if($GlibcDir{$Part1}
6978 and not $GlibcDir{$Part2}) {
6979 return 1;
6980 }
6981 elsif($GlibcDir{$Part2}
6982 and not $GlibcDir{$Part1}) {
6983 return -1;
6984 }
6985 elsif($Part1=~/glib/
6986 and $Part2!~/glib/) {
6987 return 1;
6988 }
6989 elsif($Part1!~/glib/
6990 and $Part2=~/glib/) {
6991 return -1;
6992 }
6993 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6994 return $CmpRes;
6995 }
6996 }
6997 return 0;
6998}
6999
7000sub checkRelevance($)
7001{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007002 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007003 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007004
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007005 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007006 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007007 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007008
7009 my $Name = lc(get_filename($Path));
7010 my $Dir = lc(get_dirname($Path));
7011
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007012 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007013
7014 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007015 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007016 my $Len = length($Token);
7017 next if($Len<=1);
7018 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
7019 { # include/evolution-data-server-1.4/libebook/e-book.h
7020 return 1;
7021 }
7022 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007023 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007024 return 1;
7025 }
7026 }
7027 return 0;
7028}
7029
7030sub checkFamily(@)
7031{
7032 my @Paths = @_;
7033 return 1 if($#Paths<=0);
7034 my %Prefix = ();
7035 foreach my $Path (@Paths)
7036 {
7037 if($SystemRoot) {
7038 $Path = cut_path_prefix($Path, $SystemRoot);
7039 }
7040 if(my $Dir = get_dirname($Path))
7041 {
7042 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
7043 $Prefix{$Dir} += 1;
7044 $Prefix{get_dirname($Dir)} += 1;
7045 }
7046 }
7047 foreach (sort keys(%Prefix))
7048 {
7049 if(get_depth($_)>=3
7050 and $Prefix{$_}==$#Paths+1) {
7051 return 1;
7052 }
7053 }
7054 return 0;
7055}
7056
7057sub isAcceptable($$$)
7058{
7059 my ($Header, $Candidate, $LibVersion) = @_;
7060 my $HName = get_filename($Header);
7061 if(get_dirname($Header))
7062 { # with prefix
7063 return 1;
7064 }
7065 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
7066 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
7067 return 1;
7068 }
7069 if(checkRelevance($Candidate))
7070 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
7071 return 1;
7072 }
7073 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
7074 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
7075 # /usr/include/qt4/Qt/qsslconfiguration.h
7076 return 1;
7077 }
7078 if($OStarget eq "symbian")
7079 {
7080 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
7081 return 1;
7082 }
7083 }
7084 return 0;
7085}
7086
7087sub isRelevant($$$)
7088{ # disallow to search for "abstract" headers in too deep directories
7089 my ($Header, $Candidate, $LibVersion) = @_;
7090 my $HName = get_filename($Header);
7091 if($OStarget eq "symbian")
7092 {
7093 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7094 return 0;
7095 }
7096 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007097 if($OStarget ne "bsd")
7098 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007099 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7100 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7101 return 0;
7102 }
7103 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007104 if($OStarget ne "windows")
7105 {
7106 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7107 { # skip /usr/include/wine/msvcrt
7108 return 0;
7109 }
7110 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007111 if(not get_dirname($Header)
7112 and $Candidate=~/[\/\\]wx[\/\\]/)
7113 { # do NOT search in system /wx/ directory
7114 # for headers without a prefix: sstream.h
7115 return 0;
7116 }
7117 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7118 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7119 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7120 return 0;
7121 }
7122 if($Candidate=~/[\/\\]asm-/
7123 and (my $Arch = getArch($LibVersion)) ne "unknown")
7124 { # arch-specific header files
7125 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7126 {# skip ../asm-arm/ if using x86 architecture
7127 return 0;
7128 }
7129 }
7130 my @Candidates = getSystemHeaders($HName, $LibVersion);
7131 if($#Candidates==1)
7132 { # unique header
7133 return 1;
7134 }
7135 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7136 if($#SCandidates==1)
7137 { # unique name
7138 return 1;
7139 }
7140 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7141 if(get_depth($Candidate)-$SystemDepth>=5)
7142 { # abstract headers in too deep directories
7143 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7144 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7145 return 0;
7146 }
7147 }
7148 if($Header eq "parser.h"
7149 and $Candidate!~/\/libxml2\//)
7150 { # select parser.h from xml2 library
7151 return 0;
7152 }
7153 if(not get_dirname($Header)
7154 and keys(%{$SystemHeaders{$HName}})>=3)
7155 { # many headers with the same name
7156 # like thread.h included without a prefix
7157 if(not checkFamily(@Candidates)) {
7158 return 0;
7159 }
7160 }
7161 return 1;
7162}
7163
7164sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007165{ # cache function
7166 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7167 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7168 }
7169 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7170}
7171
7172sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007173{
7174 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007175 if(-f $Header) {
7176 return $Header;
7177 }
7178 if(is_abs($Header) and not -f $Header)
7179 { # incorrect absolute path
7180 return "";
7181 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007182 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007183 { # too abstract configuration headers
7184 return "";
7185 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007186 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007187 if($OSgroup ne "windows")
7188 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007189 if(defined $WinHeaders{lc($HName)}
7190 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007191 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007192 return "";
7193 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007194 }
7195 if($OSgroup ne "macos")
7196 {
7197 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007198 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007199 return "";
7200 }
7201 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007202
7203 if(defined $ObsoleteHeaders{$HName})
7204 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007205 return "";
7206 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007207 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7208 {
7209 if(defined $AlienHeaders{$HName}
7210 or defined $AlienHeaders{$Header})
7211 { # alien headers from other systems
7212 return "";
7213 }
7214 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007215
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007216 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007217 { # search in default paths
7218 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007219 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007220 }
7221 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007222 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007223 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007224 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007225 }
7226 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7227 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7228 {
7229 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007230 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007231 }
7232 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007233 # error
7234 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007235}
7236
7237sub getSystemHeaders($$)
7238{
7239 my ($Header, $LibVersion) = @_;
7240 my @Candidates = ();
7241 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7242 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007243 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007244 next;
7245 }
7246 push(@Candidates, $Candidate);
7247 }
7248 return @Candidates;
7249}
7250
7251sub cut_path_prefix($$)
7252{
7253 my ($Path, $Prefix) = @_;
7254 return $Path if(not $Prefix);
7255 $Prefix=~s/[\/\\]+\Z//;
7256 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7257 return $Path;
7258}
7259
7260sub is_default_include_dir($)
7261{
7262 my $Dir = $_[0];
7263 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007264 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007265}
7266
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007267sub identifyHeader($$)
7268{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007269 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007270 if(not $Header) {
7271 return "";
7272 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007273 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007274 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7275 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007276 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007277 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007278}
7279
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007280sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007281{ # search for header by absolute path, relative path or name
7282 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007283 if(-f $Header)
7284 { # it's relative or absolute path
7285 return get_abs_path($Header);
7286 }
7287 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7288 and my $HeaderDir = find_in_defaults($Header))
7289 { # search for libc headers in the /usr/include
7290 # for non-libc target library before searching
7291 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007292 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007293 }
7294 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7295 { # search in the target library paths
7296 return $Path;
7297 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007298 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007299 { # search in the internal GCC include paths
7300 return $DefaultGccHeader{$Header};
7301 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007302 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007303 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007304 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007305 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007306 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007307 { # search in the default G++ include paths
7308 return $DefaultCppHeader{$Header};
7309 }
7310 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7311 { # search everywhere in the system
7312 return $AnyPath;
7313 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007314 elsif($OSgroup eq "macos")
7315 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7316 if(my $Dir = get_dirname($Header))
7317 {
7318 my $RelPath = "Headers\/".get_filename($Header);
7319 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007320 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007321 }
7322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007323 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007324 # cannot find anything
7325 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007326}
7327
7328sub getLocation($)
7329{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007330 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7331 {
7332 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007333 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007334 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007335 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007336 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007337}
7338
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007339sub getNameByInfo($)
7340{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007341 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007342 {
7343 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7344 {
7345 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7346 {
7347 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7348 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007349 my $Str = $1;
7350 if($CppMode{$Version}
7351 and $Str=~/\Ac99_(.+)\Z/)
7352 {
7353 if($CppKeywords_A{$1}) {
7354 $Str=$1;
7355 }
7356 }
7357 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007358 }
7359 }
7360 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007361 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007362 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007363}
7364
7365sub getTreeStr($)
7366{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007367 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007368 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007369 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7370 {
7371 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007372 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007373 and $Str=~/\Ac99_(.+)\Z/)
7374 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007375 if($CppKeywords_A{$1}) {
7376 $Str=$1;
7377 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007378 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007379 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007380 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007381 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007382 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007383}
7384
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007385sub getFuncShortName($)
7386{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007387 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007388 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007389 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007390 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007391 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007392 {
7393 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7394 {
7395 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7396 return "operator ".$RName;
7397 }
7398 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007399 }
7400 else
7401 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007402 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7403 {
7404 if(my $Ind = $Operator_Indication{$1}) {
7405 return "operator".$Ind;
7406 }
7407 elsif(not $UnknownOperator{$1})
7408 {
7409 printMsg("WARNING", "unknown operator $1");
7410 $UnknownOperator{$1} = 1;
7411 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007412 }
7413 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007414 }
7415 else
7416 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007417 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7418 return getTreeStr($1);
7419 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007420 }
7421 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007422 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007423}
7424
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007425sub getFuncReturn($)
7426{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007427 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7428 {
7429 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7430 {
7431 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7432 return $1;
7433 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007434 }
7435 }
7436 return "";
7437}
7438
7439sub getFuncOrig($)
7440{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007441 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7442 {
7443 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7444 return $1;
7445 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007446 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007447 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007448}
7449
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007450sub unmangleArray(@)
7451{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007452 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007453 { # MSVC mangling
7454 my $UndNameCmd = get_CmdPath("undname");
7455 if(not $UndNameCmd) {
7456 exitStatus("Not_Found", "can't find \"undname\"");
7457 }
7458 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007459 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007460 }
7461 else
7462 { # GCC mangling
7463 my $CppFiltCmd = get_CmdPath("c++filt");
7464 if(not $CppFiltCmd) {
7465 exitStatus("Not_Found", "can't find c++filt in PATH");
7466 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007467 if(not defined $CPPFILT_SUPPORT_FILE)
7468 {
7469 my $Info = `$CppFiltCmd -h 2>&1`;
7470 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7471 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007472 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007473 if($CPPFILT_SUPPORT_FILE)
7474 { # new versions of c++filt can take a file
7475 if($#_>$MAX_CPPFILT_FILE_SIZE)
7476 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7477 # this is fixed in the oncoming version of Binutils
7478 my @Half = splice(@_, 0, ($#_+1)/2);
7479 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007480 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007481 else
7482 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007483 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7484 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7485 if($?==139)
7486 { # segmentation fault
7487 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7488 }
7489 return split(/\n/, $Res);
7490 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007491 }
7492 else
7493 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007494 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7495 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007496 my @Half = splice(@_, 0, ($#_+1)/2);
7497 return (unmangleArray(@Half), unmangleArray(@_))
7498 }
7499 else
7500 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007501 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007502 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7503 if($?==139)
7504 { # segmentation fault
7505 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7506 }
7507 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007508 }
7509 }
7510 }
7511}
7512
7513sub get_SignatureNoInfo($$)
7514{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007515 my ($Symbol, $LibVersion) = @_;
7516 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
7517 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007518 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007519 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007520 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007521 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007522 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04007523 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007524 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
7525 $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;
7526 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007527 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007528 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007529 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007530 $Signature .= " [data]";
7531 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007532 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007533 $Signature .= " (...)";
7534 }
7535 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007536 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007537 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04007538 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007539 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
7540 }
7541 if($SymbolVersion) {
7542 $Signature .= $VersionSpec.$SymbolVersion;
7543 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007544 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007545}
7546
7547sub get_ChargeLevel($$)
7548{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007549 my ($Symbol, $LibVersion) = @_;
7550 return "" if($Symbol!~/\A(_Z|\?)/);
7551 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7552 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007553 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007554 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007555 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007556 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007557 return "[in-charge]";
7558 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007559 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007560 return "[not-in-charge]";
7561 }
7562 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007563 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007564 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007565 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007566 return "[in-charge]";
7567 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007568 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007569 return "[not-in-charge]";
7570 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007571 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007572 return "[in-charge-deleting]";
7573 }
7574 }
7575 }
7576 else
7577 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007578 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007579 return "[in-charge]";
7580 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007581 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007582 return "[not-in-charge]";
7583 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007584 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007585 return "[in-charge]";
7586 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007587 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007588 return "[not-in-charge]";
7589 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007590 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007591 return "[in-charge-deleting]";
7592 }
7593 }
7594 return "";
7595}
7596
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007597sub get_Signature_M($$)
7598{
7599 my ($Symbol, $LibVersion) = @_;
7600 my $Signature_M = $tr_name{$Symbol};
7601 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7602 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007603 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007604 }
7605 return $Signature_M;
7606}
7607
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007608sub get_Signature($$)
7609{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007610 my ($Symbol, $LibVersion) = @_;
7611 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7612 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007613 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007614 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
7615 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007616 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007617 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007618 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007619 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007620 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7621 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007622 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007623 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7624 {
7625 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7626 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7627 $Signature .= "~";
7628 }
7629 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007630 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007631 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007632 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007633 }
7634 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007635 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007636 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007637 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7638 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007639 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007640 else
7641 {
7642 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007643 }
7644 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007645 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007646 {
7647 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007648 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007649 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007650 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007651 if(not $ParamTypeName) {
7652 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7653 }
7654 foreach my $Typedef (keys(%ChangedTypedef))
7655 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007656 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7657 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7658 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007659 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007660 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7661 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007662 if($ParamName eq "this"
7663 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007664 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007665 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007666 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007667 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007668 }
7669 else {
7670 push(@ParamArray, $ParamTypeName);
7671 }
7672 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007673 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7674 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007675 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007676 }
7677 else
7678 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007679 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007680 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007681 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007682 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007683 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007684 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7685 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007686 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007687 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007688 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7689 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007690 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007691 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007692 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7693 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007694 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007695 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007696 }
7697 }
7698 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007699 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007700 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007701 }
7702 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007703 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007704 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007705 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007706}
7707
7708sub create_member_decl($$)
7709{
7710 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007711 if($TName=~/\([\*]+\)/)
7712 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007713 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7714 return $TName;
7715 }
7716 else
7717 {
7718 my @ArraySizes = ();
7719 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7720 push(@ArraySizes, $1);
7721 }
7722 return $TName." ".$Member.join("", @ArraySizes);
7723 }
7724}
7725
7726sub getFuncType($)
7727{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007728 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7729 {
7730 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7731 {
7732 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7733 {
7734 if($Type eq "method_type") {
7735 return "Method";
7736 }
7737 elsif($Type eq "function_type") {
7738 return "Function";
7739 }
7740 else {
7741 return "Other";
7742 }
7743 }
7744 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007745 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007746 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007747}
7748
7749sub getFuncTypeId($)
7750{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007751 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7752 {
7753 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7754 return $1;
7755 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007756 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007757 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007758}
7759
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007760sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007761{ # "._N" or "$_N" in older GCC versions
7762 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007763}
7764
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007765sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007766{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007767 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7768 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007769 }
7770
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007771 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007772
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007773 if($_[1] ne "S")
7774 {
7775 $N=~s/\A[ ]+//g;
7776 $N=~s/[ ]+\Z//g;
7777 $N=~s/[ ]{2,}/ /g;
7778 }
7779
7780 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007781
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007782 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007783
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007784 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7785 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007786
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007787 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007788
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007789 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007790
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007791 if($_[1] eq "S")
7792 {
7793 if(index($N, "operator")!=-1) {
7794 $N=~s/\b(operator[ ]*)> >/$1>>/;
7795 }
7796 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007797
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007798 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007799}
7800
7801sub get_HeaderDeps($$)
7802{
7803 my ($AbsPath, $LibVersion) = @_;
7804 return () if(not $AbsPath or not $LibVersion);
7805 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7806 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7807 }
7808 my %IncDir = ();
7809 detect_recursive_includes($AbsPath, $LibVersion);
7810 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7811 {
7812 next if(not $HeaderPath);
7813 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7814 my $Dir = get_dirname($HeaderPath);
7815 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7816 {
7817 my $Dep = $Dir;
7818 if($Prefix)
7819 {
7820 if($OSgroup eq "windows")
7821 { # case insensitive seach on windows
7822 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7823 next;
7824 }
7825 }
7826 elsif($OSgroup eq "macos")
7827 { # seach in frameworks
7828 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7829 {
7830 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7831 {# frameworks
7832 my ($HFramework, $HName) = ($1, $2);
7833 $Dep = $HFramework;
7834 }
7835 else
7836 {# mismatch
7837 next;
7838 }
7839 }
7840 }
7841 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7842 { # Linux, FreeBSD
7843 next;
7844 }
7845 }
7846 if(not $Dep)
7847 { # nothing to include
7848 next;
7849 }
7850 if(is_default_include_dir($Dep))
7851 { # included by the compiler
7852 next;
7853 }
7854 if(get_depth($Dep)==1)
7855 { # too short
7856 next;
7857 }
7858 if(isLibcDir($Dep))
7859 { # do NOT include /usr/include/{sys,bits}
7860 next;
7861 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007862 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007863 }
7864 }
7865 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7866 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7867}
7868
7869sub sortIncPaths($$)
7870{
7871 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007872 if(not $ArrRef or $#{$ArrRef}<0) {
7873 return $ArrRef;
7874 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007875 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7876 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007877 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007878 return $ArrRef;
7879}
7880
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007881sub sortDeps($$$)
7882{
7883 if($Header_Dependency{$_[2]}{$_[0]}
7884 and not $Header_Dependency{$_[2]}{$_[1]}) {
7885 return 1;
7886 }
7887 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7888 and $Header_Dependency{$_[2]}{$_[1]}) {
7889 return -1;
7890 }
7891 return 0;
7892}
7893
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007894sub join_P($$)
7895{
7896 my $S = "/";
7897 if($OSgroup eq "windows") {
7898 $S = "\\";
7899 }
7900 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007901}
7902
7903sub get_namespace_additions($)
7904{
7905 my $NameSpaces = $_[0];
7906 my ($Additions, $AddNameSpaceId) = ("", 1);
7907 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7908 {
7909 next if($SkipNameSpaces{$Version}{$NS});
7910 next if(not $NS or $NameSpaces->{$NS}==-1);
7911 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7912 next if($NS=~/\A__/i);
7913 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007914 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007915 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7916 my @NS_Parts = split(/::/, $NS);
7917 next if($#NS_Parts==-1);
7918 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7919 foreach my $NS_Part (@NS_Parts)
7920 {
7921 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7922 $TypeDecl_Suffix .= "}";
7923 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007924 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007925 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7926 $Additions.=" $TypeDecl\n $FuncDecl\n";
7927 $AddNameSpaceId+=1;
7928 }
7929 return $Additions;
7930}
7931
7932sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007933{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007934 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007935 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007936 if($Fmt eq "windows")
7937 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007938 $Path=~s/\//\\/g;
7939 $Path=lc($Path);
7940 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007941 else
7942 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007943 $Path=~s/\\/\//g;
7944 }
7945 return $Path;
7946}
7947
7948sub inc_opt($$)
7949{
7950 my ($Path, $Style) = @_;
7951 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007952 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007953 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007954 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007955 return "-I\"".path_format($Path, "unix")."\"";
7956 }
7957 elsif($OSgroup eq "macos"
7958 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007959 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007960 return "-F".esc(get_dirname($Path));
7961 }
7962 else {
7963 return "-I".esc($Path);
7964 }
7965 }
7966 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007967 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007968 }
7969 return "";
7970}
7971
7972sub platformSpecs($)
7973{
7974 my $LibVersion = $_[0];
7975 my $Arch = getArch($LibVersion);
7976 if($OStarget eq "symbian")
7977 { # options for GCCE compiler
7978 my %Symbian_Opts = map {$_=>1} (
7979 "-D__GCCE__",
7980 "-DUNICODE",
7981 "-fexceptions",
7982 "-D__SYMBIAN32__",
7983 "-D__MARM_INTERWORK__",
7984 "-D_UNICODE",
7985 "-D__S60_50__",
7986 "-D__S60_3X__",
7987 "-D__SERIES60_3X__",
7988 "-D__EPOC32__",
7989 "-D__MARM__",
7990 "-D__EABI__",
7991 "-D__MARM_ARMV5__",
7992 "-D__SUPPORT_CPP_EXCEPTIONS__",
7993 "-march=armv5t",
7994 "-mapcs",
7995 "-mthumb-interwork",
7996 "-DEKA2",
7997 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7998 );
7999 return join(" ", keys(%Symbian_Opts));
8000 }
8001 elsif($OSgroup eq "windows"
8002 and get_dumpmachine($GCC_PATH)=~/mingw/i)
8003 { # add options to MinGW compiler
8004 # to simulate the MSVC compiler
8005 my %MinGW_Opts = map {$_=>1} (
8006 "-D_WIN32",
8007 "-D_STDCALL_SUPPORTED",
8008 "-D__int64=\"long long\"",
8009 "-D__int32=int",
8010 "-D__int16=short",
8011 "-D__int8=char",
8012 "-D__possibly_notnullterminated=\" \"",
8013 "-D__nullterminated=\" \"",
8014 "-D__nullnullterminated=\" \"",
8015 "-D__w64=\" \"",
8016 "-D__ptr32=\" \"",
8017 "-D__ptr64=\" \"",
8018 "-D__forceinline=inline",
8019 "-D__inline=inline",
8020 "-D__uuidof(x)=IID()",
8021 "-D__try=",
8022 "-D__except(x)=",
8023 "-D__declspec(x)=__attribute__((x))",
8024 "-D__pragma(x)=",
8025 "-D_inline=inline",
8026 "-D__forceinline=__inline",
8027 "-D__stdcall=__attribute__((__stdcall__))",
8028 "-D__cdecl=__attribute__((__cdecl__))",
8029 "-D__fastcall=__attribute__((__fastcall__))",
8030 "-D__thiscall=__attribute__((__thiscall__))",
8031 "-D_stdcall=__attribute__((__stdcall__))",
8032 "-D_cdecl=__attribute__((__cdecl__))",
8033 "-D_fastcall=__attribute__((__fastcall__))",
8034 "-D_thiscall=__attribute__((__thiscall__))",
8035 "-DSHSTDAPI_(x)=x",
8036 "-D_MSC_EXTENSIONS",
8037 "-DSECURITY_WIN32",
8038 "-D_MSC_VER=1500",
8039 "-D_USE_DECLSPECS_FOR_SAL",
8040 "-D__noop=\" \"",
8041 "-DDECLSPEC_DEPRECATED=\" \"",
8042 "-D__builtin_alignof(x)=__alignof__(x)",
8043 "-DSORTPP_PASS");
8044 if($Arch eq "x86") {
8045 $MinGW_Opts{"-D_M_IX86=300"}=1;
8046 }
8047 elsif($Arch eq "x86_64") {
8048 $MinGW_Opts{"-D_M_AMD64=300"}=1;
8049 }
8050 elsif($Arch eq "ia64") {
8051 $MinGW_Opts{"-D_M_IA64=300"}=1;
8052 }
8053 return join(" ", keys(%MinGW_Opts));
8054 }
8055 return "";
8056}
8057
8058my %C_Structure = map {$_=>1} (
8059# FIXME: Can't separate union and struct data types before dumping,
8060# so it sometimes cause compilation errors for unknown reason
8061# when trying to declare TYPE* tmp_add_class_N
8062# This is a list of such structures + list of other C structures
8063 "sigval",
8064 "sigevent",
8065 "sigaction",
8066 "sigvec",
8067 "sigstack",
8068 "timeval",
8069 "timezone",
8070 "rusage",
8071 "rlimit",
8072 "wait",
8073 "flock",
8074 "stat",
8075 "_stat",
8076 "stat32",
8077 "_stat32",
8078 "stat64",
8079 "_stat64",
8080 "_stati64",
8081 "if_nameindex",
8082 "usb_device",
8083 "sigaltstack",
8084 "sysinfo",
8085 "timeLocale",
8086 "tcp_debug",
8087 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008088 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008089 "timespec",
8090 "random_data",
8091 "drand48_data",
8092 "_IO_marker",
8093 "_IO_FILE",
8094 "lconv",
8095 "sched_param",
8096 "tm",
8097 "itimerspec",
8098 "_pthread_cleanup_buffer",
8099 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008100 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008101 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008102 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008103 "sigcontext",
8104 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008105 # Mac
8106 "_timex",
8107 "_class_t",
8108 "_category_t",
8109 "_class_ro_t",
8110 "_protocol_t",
8111 "_message_ref_t",
8112 "_super_message_ref_t",
8113 "_ivar_t",
8114 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008115);
8116
8117sub getCompileCmd($$$)
8118{
8119 my ($Path, $Opt, $Inc) = @_;
8120 my $GccCall = $GCC_PATH;
8121 if($Opt) {
8122 $GccCall .= " ".$Opt;
8123 }
8124 $GccCall .= " -x ";
8125 if($OSgroup eq "macos") {
8126 $GccCall .= "objective-";
8127 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008128
8129 if($EMERGENCY_MODE_48)
8130 { # workaround for GCC 4.8 (C only)
8131 $GccCall .= "c++";
8132 }
8133 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008134 { # compile as "C++" header
8135 # to obtain complete dump using GCC 4.0
8136 $GccCall .= "c++-header";
8137 }
8138 else
8139 { # compile as "C++" source
8140 # GCC 3.3 cannot compile headers
8141 $GccCall .= "c++";
8142 }
8143 if(my $Opts = platformSpecs($Version))
8144 {# platform-specific options
8145 $GccCall .= " ".$Opts;
8146 }
8147 # allow extra qualifications
8148 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008149 $GccCall .= " -fpermissive";
8150 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008151 if($NoStdInc)
8152 {
8153 $GccCall .= " -nostdinc";
8154 $GccCall .= " -nostdinc++";
8155 }
8156 if($CompilerOptions{$Version})
8157 { # user-defined options
8158 $GccCall .= " ".$CompilerOptions{$Version};
8159 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008160 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008161 if($Inc)
8162 { # include paths
8163 $GccCall .= " ".$Inc;
8164 }
8165 return $GccCall;
8166}
8167
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008168sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008169{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008170 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008171 my %HeaderElems = (
8172 # Types
8173 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008174 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008175 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8176 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008177 "time.h" => ["time_t"],
8178 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008179 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8180 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008181 "stdbool.h" => ["_Bool"],
8182 "rpc/xdr.h" => ["bool_t"],
8183 "in_systm.h" => ["n_long", "n_short"],
8184 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008185 "arpa/inet.h" => ["fw_src", "ip_src"],
8186 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008187 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008188 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008189 );
8190 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008191 foreach (keys(%HeaderElems))
8192 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008193 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008194 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008195 }
8196 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008197 my %Types = ();
8198 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8199 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008200 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008201 }
8202 if(keys(%Types))
8203 {
8204 my %AddHeaders = ();
8205 foreach my $Type (keys(%Types))
8206 {
8207 if(my $Header = $AutoPreamble{$Type})
8208 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008209 if(my $Path = identifyHeader($Header, $LibVersion))
8210 {
8211 if(skipHeader($Path, $LibVersion)) {
8212 next;
8213 }
8214 $Path = path_format($Path, $OSgroup);
8215 $AddHeaders{$Path}{"Type"} = $Type;
8216 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008217 }
8218 }
8219 }
8220 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008221 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008222 }
8223 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008224 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008225}
8226
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008227sub checkCTags($)
8228{
8229 my $Path = $_[0];
8230 if(not $Path) {
8231 return;
8232 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008233 my $CTags = undef;
8234
8235 if($OSgroup eq "bsd")
8236 { # use ectags on BSD
8237 $CTags = get_CmdPath("ectags");
8238 if(not $CTags) {
8239 printMsg("WARNING", "can't find \'ectags\' program");
8240 }
8241 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008242 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008243 $CTags = get_CmdPath("ctags");
8244 }
8245 if(not $CTags)
8246 {
8247 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008248 return;
8249 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008250
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008251 if($OSgroup ne "linux")
8252 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008253 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8254 if($Info!~/exuberant/i)
8255 {
8256 printMsg("WARNING", "incompatible version of \'ctags\' program");
8257 return;
8258 }
8259 }
8260
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008261 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008262 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008263 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008264 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008265 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008266 open(CTAGS, "<", $Out);
8267 while(my $Line = <CTAGS>)
8268 {
8269 chomp($Line);
8270 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008271 if(defined $Intrinsic_Keywords{$Name})
8272 { # noise
8273 next;
8274 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008275 if($Type eq "n")
8276 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008277 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008278 next;
8279 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008280 if(index($Scpe, "struct:")==0) {
8281 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008282 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008283 if(index($Scpe, "namespace:")==0)
8284 {
8285 if($Scpe=~s/\Anamespace://) {
8286 $Name = $Scpe."::".$Name;
8287 }
8288 }
8289 $TUnit_NameSpaces{$Version}{$Name} = 1;
8290 }
8291 elsif($Type eq "p")
8292 {
8293 if(not $Scpe or index($Scpe, "namespace:")==0) {
8294 $TUnit_Funcs{$Version}{$Name} = 1;
8295 }
8296 }
8297 elsif($Type eq "x")
8298 {
8299 if(not $Scpe or index($Scpe, "namespace:")==0) {
8300 $TUnit_Vars{$Version}{$Name} = 1;
8301 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008302 }
8303 }
8304 close(CTAGS);
8305}
8306
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008307sub preChange($$)
8308{
8309 my ($HeaderPath, $IncStr) = @_;
8310
8311 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8312 my $Content = undef;
8313
8314 if($OStarget eq "windows"
8315 and get_dumpmachine($GCC_PATH)=~/mingw/i
8316 and $MinGWMode{$Version}!=-1)
8317 { # modify headers to compile by MinGW
8318 if(not $Content)
8319 { # preprocessing
8320 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8321 }
8322 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8323 { # __asm { ... }
8324 $MinGWMode{$Version}=1;
8325 }
8326 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8327 { # comments after preprocessing
8328 $MinGWMode{$Version}=1;
8329 }
8330 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8331 { # 0xffui8
8332 $MinGWMode{$Version}=1;
8333 }
8334
8335 if($MinGWMode{$Version}) {
8336 printMsg("INFO", "Using MinGW compatibility mode");
8337 }
8338 }
8339
8340 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8341 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8342 { # rename C++ keywords in C code
8343 # disable this code by -cpp-compatible option
8344 if(not $Content)
8345 { # preprocessing
8346 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8347 }
8348 my $RegExp_C = join("|", keys(%CppKeywords_C));
8349 my $RegExp_F = join("|", keys(%CppKeywords_F));
8350 my $RegExp_O = join("|", keys(%CppKeywords_O));
8351
8352 my $Detected = undef;
8353
8354 while($Content=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*(\,|\)|\;|\-\>|\.|\:\s*\d))/$1$2c99_$3$4/g)
8355 { # MATCH:
8356 # int foo(int new, int class, int (*new)(int));
8357 # unsigned private: 8;
8358 # DO NOT MATCH:
8359 # #pragma GCC visibility push(default)
8360 $CppMode{$Version} = 1;
8361 $Detected = "$1$2$3$4" if(not defined $Detected);
8362 }
8363 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8364 { # MATCH:
8365 # int delete(...);
8366 # int explicit(...);
8367 # DO NOT MATCH:
8368 # void operator delete(...)
8369 $CppMode{$Version} = 1;
8370 $Detected = "$1$2$3" if(not defined $Detected);
8371 }
8372 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8373 { # MATCH:
8374 # int bool;
8375 # DO NOT MATCH:
8376 # bool X;
8377 # return *this;
8378 # throw;
8379 $CppMode{$Version} = 1;
8380 $Detected = "$1$2$3" if(not defined $Detected);
8381 }
8382 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8383 { # MATCH:
8384 # int operator(...);
8385 # DO NOT MATCH:
8386 # int operator()(...);
8387 $CppMode{$Version} = 1;
8388 $Detected = "$1$2$3" if(not defined $Detected);
8389 }
8390 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8391 { # MATCH:
8392 # int foo(int operator);
8393 # int foo(int operator, int other);
8394 # DO NOT MATCH:
8395 # int operator,(...);
8396 $CppMode{$Version} = 1;
8397 $Detected = "$1$2$3" if(not defined $Detected);
8398 }
8399 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8400 { # MATCH:
8401 # int foo(gboolean *bool);
8402 # DO NOT MATCH:
8403 # void setTabEnabled(int index, bool);
8404 $CppMode{$Version} = 1;
8405 $Detected = "$1$2$3" if(not defined $Detected);
8406 }
8407 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8408 { # MATCH:
8409 # int foo(int* this);
8410 # int bar(int this);
8411 # int baz(int throw);
8412 # DO NOT MATCH:
8413 # foo(X, this);
8414 $CppMode{$Version} = 1;
8415 $Detected = "$1$2$3$4" if(not defined $Detected);
8416 }
8417 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8418 { # MATCH:
8419 # struct template {...};
8420 # extern template foo(...);
8421 $CppMode{$Version} = 1;
8422 $Detected = "$1$2" if(not defined $Detected);
8423 }
8424
8425 if($CppMode{$Version} == 1)
8426 {
8427 if($Debug)
8428 {
8429 $Detected=~s/\A\s+//g;
8430 printMsg("INFO", "Detected code: \"$Detected\"");
8431 }
8432 }
8433
8434 # remove typedef enum NAME NAME;
8435 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8436 my $N = 0;
8437 while($N<=$#FwdTypedefs-1)
8438 {
8439 my $S = $FwdTypedefs[$N];
8440 if($S eq $FwdTypedefs[$N+1])
8441 {
8442 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008443 $CppMode{$Version} = 1;
8444
8445 if($Debug) {
8446 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8447 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008448 }
8449 $N+=2;
8450 }
8451
8452 if($CppMode{$Version}==1) {
8453 printMsg("INFO", "Using C++ compatibility mode");
8454 }
8455 }
8456
8457 if($CppMode{$Version}==1
8458 or $MinGWMode{$Version}==1)
8459 {
8460 my $IPath = $TMP_DIR."/dump$Version.i";
8461 writeFile($IPath, $Content);
8462 return $IPath;
8463 }
8464
8465 return undef;
8466}
8467
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008468sub getDump()
8469{
8470 if(not $GCC_PATH) {
8471 exitStatus("Error", "internal error - GCC path is not set");
8472 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008473
8474 my @Headers = keys(%{$Registered_Headers{$Version}});
8475 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8476
8477 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8478
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008479 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008480 my $HeaderPath = $TmpHeaderPath;
8481
8482 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008483 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008484 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8485 {
8486 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008487 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008488 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008489 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008490 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8491 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008492 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008493 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008494 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008495 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8496 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8497 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008498 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008499 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008500
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008501 if($ExtraInfo)
8502 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008503 if($IncludeString) {
8504 writeFile($ExtraInfo."/include-string", $IncludeString);
8505 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008506 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8507 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008508
8509 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8510 {
8511 my $REDIR = "";
8512 foreach my $P1 (sort @Redirects) {
8513 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8514 }
8515 writeFile($ExtraInfo."/include-redirect", $REDIR);
8516 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008517 }
8518
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008519 if(not keys(%{$TargetHeaders{$Version}}))
8520 { # Target headers
8521 addTargetHeaders($Version);
8522 }
8523
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008524 # clean memory
8525 %RecursiveIncludes = ();
8526 %Header_Include_Prefix = ();
8527 %Header_Includes = ();
8528
8529 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008530 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008531 delete($Cache{"detect_header_includes"});
8532 delete($Cache{"selectSystemHeader"});
8533
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008534 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008535 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8536 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008537
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008538 if($ExtraInfo)
8539 { # extra information for other tools
8540 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8541 }
8542
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008543 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008544 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008545 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008546
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008547 if($COMMON_LANGUAGE{$Version} eq "C++") {
8548 checkCTags($Pre);
8549 }
8550
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008551 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8552 { # try to correct the preprocessor output
8553 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008554 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008555
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008556 if($COMMON_LANGUAGE{$Version} eq "C++")
8557 { # add classes and namespaces to the dump
8558 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008559 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008560 or $MinGWMode{$Version}==1) {
8561 $CHdump .= " -fpreprocessed";
8562 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008563 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008564 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008565 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008566 chdir($ORIG_DIR);
8567 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8568 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008569 my $Content = readFile($ClassDump);
8570 foreach my $ClassInfo (split(/\n\n/, $Content))
8571 {
8572 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8573 {
8574 my $CName = $1;
8575 next if($CName=~/\A(__|_objc_|_opaque_)/);
8576 $TUnit_NameSpaces{$Version}{$CName} = -1;
8577 if($CName=~/\A[\w:]+\Z/)
8578 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008579 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008580 }
8581 if($CName=~/(\w[\w:]*)::/)
8582 { # namespaces
8583 my $NS = $1;
8584 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8585 $TUnit_NameSpaces{$Version}{$NS} = 1;
8586 }
8587 }
8588 }
8589 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8590 { # read v-tables (advanced approach)
8591 my ($CName, $VTable) = ($1, $2);
8592 $ClassVTable_Content{$Version}{$CName} = $VTable;
8593 }
8594 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008595 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8596 { # add user-defined namespaces
8597 $TUnit_NameSpaces{$Version}{$NS} = 1;
8598 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008599 if($Debug)
8600 { # debug mode
8601 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008602 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008603 }
8604 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008605 }
8606
8607 # add namespaces and classes
8608 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8609 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008610 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008611 }
8612 # some GCC versions don't include class methods to the TU dump by default
8613 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008614 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008615 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8616 {
8617 next if($C_Structure{$CName});
8618 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008619 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008620 if(not $Force and $GCC_44
8621 and $OSgroup eq "linux")
8622 { # optimization for linux with GCC >= 4.4
8623 # disable this code by -force option
8624 if(index($CName, "::")!=-1)
8625 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008626 next;
8627 }
8628 }
8629 else
8630 {
8631 if($CName=~/\A(.+)::[^:]+\Z/
8632 and $TUnit_Classes{$Version}{$1})
8633 { # classes inside other classes
8634 next;
8635 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008636 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008637 if(defined $TUnit_Funcs{$Version}{$CName})
8638 { # the same name for a function and type
8639 next;
8640 }
8641 if(defined $TUnit_Vars{$Version}{$CName})
8642 { # the same name for a variable and type
8643 next;
8644 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008645 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8646 }
8647 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008648 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008649 }
8650 }
8651 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8652 # create TU dump
8653 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008654 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008655 or $MinGWMode{$Version}==1) {
8656 $TUdump .= " -fpreprocessed";
8657 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008658 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008659 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8660 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008661 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008662 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008663 if($?)
8664 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008665 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008666 { # try to recompile
8667 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008668 if($CppMode{$Version}==1
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008669 and index($Errors, "c99_")!=-1)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008670 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008671 $CppMode{$Version}=-1;
8672 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008673 resetLogging($Version);
8674 $TMP_DIR = tempdir(CLEANUP=>1);
8675 return getDump();
8676 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008677 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008678 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008679 { # add auto preamble headers and try again
8680 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008681 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008682 foreach my $Num (0 .. $#Headers)
8683 {
8684 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008685 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8686 {
8687 push_U($Include_Preamble{$Version}, $Path);
8688 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008689 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008690 }
8691 resetLogging($Version);
8692 $TMP_DIR = tempdir(CLEANUP=>1);
8693 return getDump();
8694 }
8695 elsif($Cpp0xMode{$Version}!=-1
8696 and ($Errors=~/\Q-std=c++0x\E/
8697 or $Errors=~/is not a class or namespace/))
8698 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008699 if(check_gcc($GCC_PATH, "4.6"))
8700 {
8701 $Cpp0xMode{$Version}=-1;
8702 printMsg("INFO", "Enabling c++0x mode");
8703 resetLogging($Version);
8704 $TMP_DIR = tempdir(CLEANUP=>1);
8705 $CompilerOptions{$Version} .= " -std=c++0x";
8706 return getDump();
8707 }
8708 else {
8709 printMsg("WARNING", "Probably c++0x construction detected");
8710 }
8711
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008712 }
8713 elsif($MinGWMode{$Version}==1)
8714 { # disable MinGW mode and try again
8715 $MinGWMode{$Version}=-1;
8716 resetLogging($Version);
8717 $TMP_DIR = tempdir(CLEANUP=>1);
8718 return getDump();
8719 }
8720 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008721 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008722 else {
8723 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008724 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008725 printMsg("ERROR", "some errors occurred when compiling headers");
8726 printErrorLog($Version);
8727 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008728 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008729 }
8730 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008731 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008732 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008733
8734 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8735 return $TUs[0];
8736 }
8737 else
8738 {
8739 my $Msg = "can't compile header(s)";
8740 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8741 $Msg .= "\nDid you install G++?";
8742 }
8743 exitStatus("Cannot_Compile", $Msg);
8744 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008745}
8746
8747sub cmd_file($)
8748{
8749 my $Path = $_[0];
8750 return "" if(not $Path or not -e $Path);
8751 if(my $CmdPath = get_CmdPath("file")) {
8752 return `$CmdPath -b \"$Path\"`;
8753 }
8754 return "";
8755}
8756
8757sub getIncString($$)
8758{
8759 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008760 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008761 my $String = "";
8762 foreach (@{$ArrRef}) {
8763 $String .= " ".inc_opt($_, $Style);
8764 }
8765 return $String;
8766}
8767
8768sub getIncPaths(@)
8769{
8770 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008771 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008772 if($INC_PATH_AUTODETECT{$Version})
8773 { # auto-detecting dependencies
8774 my %Includes = ();
8775 foreach my $HPath (@HeaderPaths)
8776 {
8777 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8778 {
8779 if($Skip_Include_Paths{$Version}{$Dir}) {
8780 next;
8781 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008782 if($SystemRoot)
8783 {
8784 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8785 next;
8786 }
8787 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008788 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008789 }
8790 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008791 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008792 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008793 }
8794 }
8795 else
8796 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008797 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008798 }
8799 return \@IncPaths;
8800}
8801
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008802sub push_U($@)
8803{ # push unique
8804 if(my $Array = shift @_)
8805 {
8806 if(@_)
8807 {
8808 my %Exist = map {$_=>1} @{$Array};
8809 foreach my $Elem (@_)
8810 {
8811 if(not defined $Exist{$Elem})
8812 {
8813 push(@{$Array}, $Elem);
8814 $Exist{$Elem} = 1;
8815 }
8816 }
8817 }
8818 }
8819}
8820
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008821sub callPreprocessor($$$)
8822{
8823 my ($Path, $Inc, $LibVersion) = @_;
8824 return "" if(not $Path or not -f $Path);
8825 my $IncludeString=$Inc;
8826 if(not $Inc) {
8827 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8828 }
8829 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008830 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008831 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008832 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008833}
8834
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008835sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008836{ # native "find" is much faster than File::Find (~6x)
8837 # also the File::Find doesn't support --maxdepth N option
8838 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008839 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008840 return () if(not $Path or not -e $Path);
8841 if($OSgroup eq "windows")
8842 {
8843 my $DirCmd = get_CmdPath("dir");
8844 if(not $DirCmd) {
8845 exitStatus("Not_Found", "can't find \"dir\" command");
8846 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008847 $Path = get_abs_path($Path);
8848 $Path = path_format($Path, $OSgroup);
8849 my $Cmd = $DirCmd." \"$Path\" /B /O";
8850 if($MaxDepth!=1) {
8851 $Cmd .= " /S";
8852 }
8853 if($Type eq "d") {
8854 $Cmd .= " /AD";
8855 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008856 elsif($Type eq "f") {
8857 $Cmd .= " /A-D";
8858 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008859 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008860 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008861 {
8862 if(not $UseRegex)
8863 { # FIXME: how to search file names in MS shell?
8864 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008865 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008866 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008867 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008868 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008869 }
8870 my @AbsPaths = ();
8871 foreach my $File (@Files)
8872 {
8873 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008874 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008875 }
8876 if($Type eq "f" and not -f $File)
8877 { # skip dirs
8878 next;
8879 }
8880 push(@AbsPaths, path_format($File, $OSgroup));
8881 }
8882 if($Type eq "d") {
8883 push(@AbsPaths, $Path);
8884 }
8885 return @AbsPaths;
8886 }
8887 else
8888 {
8889 my $FindCmd = get_CmdPath("find");
8890 if(not $FindCmd) {
8891 exitStatus("Not_Found", "can't find a \"find\" command");
8892 }
8893 $Path = get_abs_path($Path);
8894 if(-d $Path and -l $Path
8895 and $Path!~/\/\Z/)
8896 { # for directories that are symlinks
8897 $Path.="/";
8898 }
8899 my $Cmd = $FindCmd." \"$Path\"";
8900 if($MaxDepth) {
8901 $Cmd .= " -maxdepth $MaxDepth";
8902 }
8903 if($Type) {
8904 $Cmd .= " -type $Type";
8905 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008906 if($Name and not $UseRegex)
8907 { # wildcards
8908 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008909 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008910 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008911 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008912 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8913 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008914 my @Files = split(/\n/, $Res);
8915 if($Name and $UseRegex)
8916 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008917 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008918 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008919 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008920 }
8921}
8922
8923sub unpackDump($)
8924{
8925 my $Path = $_[0];
8926 return "" if(not $Path or not -e $Path);
8927 $Path = get_abs_path($Path);
8928 $Path = path_format($Path, $OSgroup);
8929 my ($Dir, $FileName) = separate_path($Path);
8930 my $UnpackDir = $TMP_DIR."/unpack";
8931 rmtree($UnpackDir);
8932 mkpath($UnpackDir);
8933 if($FileName=~s/\Q.zip\E\Z//g)
8934 { # *.zip
8935 my $UnzipCmd = get_CmdPath("unzip");
8936 if(not $UnzipCmd) {
8937 exitStatus("Not_Found", "can't find \"unzip\" command");
8938 }
8939 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008940 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008941 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008942 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008943 }
8944 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008945 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008946 if(not @Contents) {
8947 exitStatus("Error", "can't extract \'$Path\'");
8948 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008949 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008950 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008951 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008952 { # *.tar.gz
8953 if($OSgroup eq "windows")
8954 { # -xvzf option is not implemented in tar.exe (2003)
8955 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8956 my $TarCmd = get_CmdPath("tar");
8957 if(not $TarCmd) {
8958 exitStatus("Not_Found", "can't find \"tar\" command");
8959 }
8960 my $GzipCmd = get_CmdPath("gzip");
8961 if(not $GzipCmd) {
8962 exitStatus("Not_Found", "can't find \"gzip\" command");
8963 }
8964 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008965 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008966 if($?) {
8967 exitStatus("Error", "can't extract \'$Path\'");
8968 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008969 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008970 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008971 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008972 }
8973 chdir($ORIG_DIR);
8974 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008975 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008976 if(not @Contents) {
8977 exitStatus("Error", "can't extract \'$Path\'");
8978 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008979 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008980 }
8981 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008982 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008983 my $TarCmd = get_CmdPath("tar");
8984 if(not $TarCmd) {
8985 exitStatus("Not_Found", "can't find \"tar\" command");
8986 }
8987 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008988 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008989 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008990 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008991 }
8992 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008993 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008994 if(not @Contents) {
8995 exitStatus("Error", "can't extract \'$Path\'");
8996 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008997 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008998 }
8999 }
9000}
9001
9002sub createArchive($$)
9003{
9004 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009005 if(not $To) {
9006 $To = ".";
9007 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009008 if(not $Path or not -e $Path
9009 or not -d $To) {
9010 return "";
9011 }
9012 my ($From, $Name) = separate_path($Path);
9013 if($OSgroup eq "windows")
9014 { # *.zip
9015 my $ZipCmd = get_CmdPath("zip");
9016 if(not $ZipCmd) {
9017 exitStatus("Not_Found", "can't find \"zip\"");
9018 }
9019 my $Pkg = $To."/".$Name.".zip";
9020 unlink($Pkg);
9021 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04009022 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009023 if($?)
9024 { # cannot allocate memory (or other problems with "zip")
9025 unlink($Path);
9026 exitStatus("Error", "can't pack the ABI dump: ".$!);
9027 }
9028 chdir($ORIG_DIR);
9029 unlink($Path);
9030 return $Pkg;
9031 }
9032 else
9033 { # *.tar.gz
9034 my $TarCmd = get_CmdPath("tar");
9035 if(not $TarCmd) {
9036 exitStatus("Not_Found", "can't find \"tar\"");
9037 }
9038 my $GzipCmd = get_CmdPath("gzip");
9039 if(not $GzipCmd) {
9040 exitStatus("Not_Found", "can't find \"gzip\"");
9041 }
9042 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
9043 unlink($Pkg);
9044 chdir($From);
9045 system($TarCmd, "-czf", $Pkg, $Name);
9046 if($?)
9047 { # cannot allocate memory (or other problems with "tar")
9048 unlink($Path);
9049 exitStatus("Error", "can't pack the ABI dump: ".$!);
9050 }
9051 chdir($ORIG_DIR);
9052 unlink($Path);
9053 return $To."/".$Name.".tar.gz";
9054 }
9055}
9056
9057sub is_header_file($)
9058{
9059 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
9060 return $_[0];
9061 }
9062 return 0;
9063}
9064
9065sub is_not_header($)
9066{
9067 if($_[0]=~/\.\w+\Z/
9068 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
9069 return 1;
9070 }
9071 return 0;
9072}
9073
9074sub is_header($$$)
9075{
9076 my ($Header, $UserDefined, $LibVersion) = @_;
9077 return 0 if(-d $Header);
9078 if(-f $Header) {
9079 $Header = get_abs_path($Header);
9080 }
9081 else
9082 {
9083 if(is_abs($Header))
9084 { # incorrect absolute path
9085 return 0;
9086 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009087 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009088 $Header = $HPath;
9089 }
9090 else
9091 { # can't find header
9092 return 0;
9093 }
9094 }
9095 if($Header=~/\.\w+\Z/)
9096 { # have an extension
9097 return is_header_file($Header);
9098 }
9099 else
9100 {
9101 if($UserDefined==2)
9102 { # specified on the command line
9103 if(cmd_file($Header)!~/HTML|XML/i) {
9104 return $Header;
9105 }
9106 }
9107 elsif($UserDefined)
9108 { # specified in the XML-descriptor
9109 # header file without an extension
9110 return $Header;
9111 }
9112 else
9113 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009114 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009115 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009116 { # !~/HTML|XML|shared|dynamic/i
9117 return $Header;
9118 }
9119 }
9120 }
9121 return 0;
9122}
9123
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009124sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009125{
9126 my $LibVersion = $_[0];
9127 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9128 {
9129 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009130 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009131
9132 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9133 detect_recursive_includes($RegHeader, $LibVersion);
9134 }
9135
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009136 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9137 {
9138 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009139
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009140 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009141 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9142 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009143 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009144 }
9145 }
9146 }
9147}
9148
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009149sub familiarDirs($$)
9150{
9151 my ($D1, $D2) = @_;
9152 if($D1 eq $D2) {
9153 return 1;
9154 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009155
9156 my $U1 = index($D1, "/usr/");
9157 my $U2 = index($D2, "/usr/");
9158
9159 if($U1==0 and $U2!=0) {
9160 return 0;
9161 }
9162
9163 if($U2==0 and $U1!=0) {
9164 return 0;
9165 }
9166
9167 if(index($D2, $D1."/")==0) {
9168 return 1;
9169 }
9170
9171 # /usr/include/DIR
9172 # /home/user/DIR
9173
9174 my $DL = get_depth($D1);
9175
9176 my @Dirs1 = ($D1);
9177 while($DL - get_depth($D1)<=2
9178 and get_depth($D1)>=4
9179 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9180 push(@Dirs1, $D1);
9181 }
9182
9183 my @Dirs2 = ($D2);
9184 while(get_depth($D2)>=4
9185 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9186 push(@Dirs2, $D2);
9187 }
9188
9189 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009190 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009191 foreach my $P2 (@Dirs2)
9192 {
9193
9194 if($P1 eq $P2) {
9195 return 1;
9196 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009197 }
9198 }
9199 return 0;
9200}
9201
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009202sub readHeaders($)
9203{
9204 $Version = $_[0];
9205 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9206 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009207 if($Debug)
9208 { # debug mode
9209 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009210 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009211 }
9212 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009213}
9214
9215sub prepareTypes($)
9216{
9217 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009218 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009219 { # support for old ABI dumps
9220 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009221 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009222 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009223 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9224 if($TName=~/\A(\w+)::(\w+)/) {
9225 my ($P1, $P2) = ($1, $2);
9226 if($P1 eq $P2) {
9227 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009228 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009229 else {
9230 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9231 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009232 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009233 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009234 }
9235 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009236 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009237 { # support for old ABI dumps
9238 # V < 2.5: array size == "number of elements"
9239 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009240 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009241 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009242 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009243 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009244 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009245 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009246 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009247 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009248 $Size *= $Base{"Size"};
9249 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009250 }
9251 else
9252 { # array[] is a pointer
9253 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009254 }
9255 }
9256 }
9257 }
9258 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009259 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009260 { # support for old ABI dumps
9261 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009262 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009263 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009264 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009265 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009266 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009267 my %Type = get_Type($TypeId, $LibVersion);
9268 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9269 my %Type2 = get_Type($TypeId_2, $V2);
9270 if($Type{"Size"} ne $Type2{"Size"}) {
9271 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009272 }
9273 }
9274 }
9275 }
9276}
9277
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009278sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009279{
9280 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009281
9282 if(not keys(%{$SymbolInfo{$LibVersion}}))
9283 { # check if input is valid
9284 if(not $ExtendedCheck and not $CheckObjectsOnly)
9285 {
9286 if($CheckHeadersOnly) {
9287 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9288 }
9289 else {
9290 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9291 }
9292 }
9293 }
9294
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009295 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009296 if(not checkDump(1, "2.10")
9297 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009298 { # different formats
9299 $Remangle = 1;
9300 }
9301 if($CheckHeadersOnly)
9302 { # different languages
9303 if($UserLang)
9304 { # --lang=LANG for both versions
9305 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9306 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9307 {
9308 if($UserLang eq "C++")
9309 { # remangle symbols
9310 $Remangle = 1;
9311 }
9312 elsif($UserLang eq "C")
9313 { # remove mangling
9314 $Remangle = -1;
9315 }
9316 }
9317 }
9318 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009319
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009320 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009321 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009322 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009323 { # support for old ABI dumps
9324 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9325 {
9326 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9327 {
9328 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9329 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009330 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009331 if(defined $DVal and $DVal ne "")
9332 {
9333 if($TName eq "char") {
9334 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9335 }
9336 elsif($TName eq "bool") {
9337 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9338 }
9339 }
9340 }
9341 }
9342 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009343 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009344 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009345 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9346 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009347 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009348 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9349 # + support for old ABI dumps
9350 next;
9351 }
9352 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009353 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009354 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009355 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009356 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009357
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009358 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009359 if(not checkDump(1, "2.12")
9360 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009361 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009362 if($ShortName eq "operator>>")
9363 {
9364 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9365 { # corrected mangling of operator>>
9366 $SRemangle = 1;
9367 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009368 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009369 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9370 {
9371 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9372 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9373 { # corrected mangling of const global data
9374 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9375 # and incorrectly mangled by old ACC versions
9376 $SRemangle = 1;
9377 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009378 }
9379 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009380 if(not $CheckHeadersOnly)
9381 { # support for old ABI dumps
9382 if(not checkDump(1, "2.17")
9383 or not checkDump(2, "2.17"))
9384 {
9385 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9386 {
9387 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9388 {
9389 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9390 {
9391 $MnglName = $ShortName;
9392 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9393 }
9394 }
9395 }
9396 }
9397 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009398 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009399 { # support for old ABI dumps: some symbols are not mangled in old dumps
9400 # mangle both sets of symbols (old and new)
9401 # NOTE: remangling all symbols by the same mangler
9402 if($MnglName=~/\A_ZN(V|)K/)
9403 { # mangling may be incorrect on old ABI dumps
9404 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009405 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009406 }
9407 if($MnglName=~/\A_ZN(K|)V/)
9408 { # mangling may be incorrect on old ABI dumps
9409 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009410 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009411 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009412 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9413 or (not $ClassID and $CheckHeadersOnly)
9414 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9415 { # support for old ABI dumps, GCC >= 4.0
9416 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009417 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009418 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009419 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009420 $MangledNames{$LibVersion}{$MnglName} = 1;
9421 }
9422 }
9423 }
9424 elsif($Remangle==-1)
9425 { # remove mangling
9426 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009427 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009428 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009429 if(not $MnglName) {
9430 next;
9431 }
9432 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9433 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009434 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9435
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009436 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009437 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009438 { # support for old dumps
9439 # add "Volatile" attribute
9440 if($MnglName=~/_Z(K|)V/) {
9441 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9442 }
9443 }
9444 # symbol and its symlink have same signatures
9445 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009446 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009447 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009448
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009449 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9450 {
9451 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9452 if($SymVer{$LibVersion}{$Alias}) {
9453 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9454 }
9455 }
9456
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009457 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009458 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009459 }
9460 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9461 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9462 }
9463 if($ExtendedCheck)
9464 { # --ext option
9465 addExtension($LibVersion);
9466 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009467
9468 # clean memory
9469 delete($SymbolInfo{$LibVersion});
9470
9471 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009472 { # detect allocable classes with public exported constructors
9473 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009474 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009475 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009476 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009477 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009478 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9479 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009480 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009481 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009482 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009483 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009484 $AllocableClass{$LibVersion}{$ClassName} = 1;
9485 }
9486 }
9487 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009488 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009489 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009490 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009491 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009492 if($CheckHeadersOnly)
9493 {
9494 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9495 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9496 { # all symbols except non-virtual inline
9497 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9498 }
9499 }
9500 else {
9501 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009502 }
9503 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009504 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009505 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009506 }
9507 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009508 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009509 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009510 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009511 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009512 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009513 if(defined $Base{"Type"}
9514 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009515 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009516 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009517 if($Name=~/<([^<>\s]+)>/)
9518 {
9519 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9520 $ReturnedClass{$LibVersion}{$Tid} = 1;
9521 }
9522 }
9523 else {
9524 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9525 }
9526 }
9527 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009528 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009529 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009530 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009531 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009532 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009533 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009534 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009535 if($Base{"Type"}=~/Struct|Class/)
9536 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009537 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009538 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9539 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009540 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009541 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009542 }
9543 }
9544 }
9545 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009546
9547 # mapping {short name => symbols}
9548 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009549 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009550 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009551 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009552 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009553 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009554 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009555 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009556 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9557 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009558 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009559 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009560 }
9561 }
9562 }
9563 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009564
9565 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009566 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009567 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009568 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009569 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009570 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9571 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009572 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009573 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009574 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009575 $ClassNames{$LibVersion}{$TName} = 1;
9576 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009577 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009578 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9579 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009580 }
9581 }
9582 }
9583 }
9584 }
9585}
9586
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009587sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009588{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009589 my ($Tid, $LibVersion) = @_;
9590 if(not $Tid) {
9591 return $Tid;
9592 }
9593
9594 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9595 {
9596 if($TName_Tid{$LibVersion}{$Name}) {
9597 return $TName_Tid{$LibVersion}{$Name};
9598 }
9599 }
9600
9601 return $Tid;
9602}
9603
9604sub register_SymbolUsage($$$)
9605{
9606 my ($InfoId, $UsedType, $LibVersion) = @_;
9607
9608 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9609 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9610 {
9611 register_TypeUsage($RTid, $UsedType, $LibVersion);
9612 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9613 }
9614 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9615 {
9616 register_TypeUsage($FCid, $UsedType, $LibVersion);
9617 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9618
9619 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9620 { # register "this" pointer
9621 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9622 }
9623 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9624 { # register "this" pointer (const method)
9625 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9626 }
9627 }
9628 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9629 {
9630 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9631 {
9632 register_TypeUsage($PTid, $UsedType, $LibVersion);
9633 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9634 }
9635 }
9636 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9637 {
9638 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9639 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9640 register_TypeUsage($TTid, $UsedType, $LibVersion);
9641 }
9642 }
9643}
9644
9645sub register_TypeUsage($$$)
9646{
9647 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009648 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009649 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009650 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009651 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009652 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009653 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009654 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009655
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009656 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009657 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009658 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009659 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009660 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009661 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9662 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9663 }
9664 }
9665
9666 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9667 {
9668 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009669 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009670 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009671 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9672 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009673 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009674 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9675 {
9676 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9677 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009678 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009679 }
9680 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009681 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009682 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009683 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009684 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9685 {
9686 register_TypeUsage($MTid, $UsedType, $LibVersion);
9687 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009688 }
9689 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009690 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009691 or $TInfo{"Type"} eq "MethodPtr"
9692 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009693 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009694 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009695 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009696 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009697 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009698 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009699 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9700 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009701 }
9702 }
9703 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009704 if($TInfo{"Type"} eq "FieldPtr")
9705 {
9706 if(my $RTid = $TInfo{"Return"}) {
9707 register_TypeUsage($RTid, $UsedType, $LibVersion);
9708 }
9709 if(my $CTid = $TInfo{"Class"}) {
9710 register_TypeUsage($CTid, $UsedType, $LibVersion);
9711 }
9712 }
9713 if($TInfo{"Type"} eq "MethodPtr")
9714 {
9715 if(my $CTid = $TInfo{"Class"}) {
9716 register_TypeUsage($CTid, $UsedType, $LibVersion);
9717 }
9718 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009719 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009720 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009721 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009722 $UsedType->{$TypeId} = 1;
9723 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9724 {
9725 register_TypeUsage($BTid, $UsedType, $LibVersion);
9726 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9727 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009728 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009729 else
9730 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9731 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009732 }
9733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009734}
9735
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009736sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009737{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009738 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9739
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009740 if($Level eq "Dump")
9741 {
9742 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9743 { # TODO: check if this symbol is from
9744 # base classes of other target symbols
9745 return 1;
9746 }
9747 }
9748
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009749 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9750 { # stdc++ interfaces
9751 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009752 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009753
9754 my $Target = 0;
9755 if(my $Header = $SInfo->{"Header"}) {
9756 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9757 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009758 if($ExtendedCheck)
9759 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009760 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009761 $Target = 1;
9762 }
9763 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009764 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009765 {
9766 if($Target)
9767 {
9768 if($Level eq "Dump")
9769 { # dumped
9770 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009771 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009772 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009773 return 1;
9774 }
9775 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009776 else {
9777 return 1;
9778 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009779 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009780 elsif($Level eq "Source")
9781 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009782 return 1;
9783 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009784 elsif($Level eq "Binary")
9785 { # checked
9786 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9787 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9788 return 1;
9789 }
9790 }
9791 }
9792 }
9793 else
9794 { # library is available
9795 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9796 { # exported symbols
9797 return 1;
9798 }
9799 if($Level eq "Dump")
9800 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009801 if($BinaryOnly)
9802 {
9803 if($SInfo->{"Data"})
9804 {
9805 if($Target) {
9806 return 1;
9807 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009808 }
9809 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009810 else
9811 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009812 if($Target) {
9813 return 1;
9814 }
9815 }
9816 }
9817 elsif($Level eq "Source")
9818 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009819 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
9820 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009821 { # skip LOCAL symbols
9822 if($Target) {
9823 return 1;
9824 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009825 }
9826 }
9827 elsif($Level eq "Binary")
9828 { # checked
9829 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9830 {
9831 if($Target) {
9832 return 1;
9833 }
9834 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009835 }
9836 }
9837 return 0;
9838}
9839
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009840sub cleanDump($)
9841{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009842 my $LibVersion = $_[0];
9843 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9844 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009845 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9846 {
9847 delete($SymbolInfo{$LibVersion}{$InfoId});
9848 next;
9849 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009850 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009851 if(not $MnglName)
9852 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009853 delete($SymbolInfo{$LibVersion}{$InfoId});
9854 next;
9855 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009856 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009857 if(not $ShortName)
9858 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009859 delete($SymbolInfo{$LibVersion}{$InfoId});
9860 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009861 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009862 if($MnglName eq $ShortName)
9863 { # remove duplicate data
9864 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009865 }
9866 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9867 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9868 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009869 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9870 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9871 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009872 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009873 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009874 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009875 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009876 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9877 {
9878 delete($TypeInfo{$LibVersion}{$Tid});
9879 next;
9880 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009881 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009882 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009883 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009884 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9885 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9886 }
9887 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009888 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9889 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9890 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009891 }
9892}
9893
9894sub selectType($$)
9895{
9896 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009897
9898 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9899 {
9900 if(defined $TypeInfo{$LibVersion}{$Dupl})
9901 {
9902 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9903 { # duplicate
9904 return 0;
9905 }
9906 }
9907 }
9908
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009909 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9910 {
9911 if(not isBuiltIn($THeader))
9912 {
9913 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009914 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009915 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9916 {
9917 if(is_target_header($THeader, $LibVersion))
9918 { # from target headers
9919 if(not selfTypedef($Tid, $LibVersion)) {
9920 return 1;
9921 }
9922 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009923 }
9924 }
9925 }
9926 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009927 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009928}
9929
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009930sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009931{ # remove unused data types from the ABI dump
9932 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009933
9934 my %UsedType = ();
9935
9936 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009937 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009938 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009939 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009940 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009941 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009942 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009943 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009944 next;
9945 }
9946
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009947 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009948 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009949 if(selectType($Tid, $LibVersion))
9950 {
9951 my %Tree = ();
9952 register_TypeUsage($Tid, \%Tree, $LibVersion);
9953
9954 my $Tmpl = 0;
9955 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9956 {
9957 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9958 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9959 {
9960 $Tmpl = 1;
9961 last;
9962 }
9963 }
9964 if(not $Tmpl)
9965 {
9966 foreach (keys(%Tree)) {
9967 $UsedType{$_} = 1;
9968 }
9969 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009970 }
9971 }
9972 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009973
9974 my %Delete = ();
9975
9976 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009977 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009978 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009979 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009980 next;
9981 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009982
9983 if($Kind eq "Extra")
9984 {
9985 my %Tree = ();
9986 register_TypeUsage($Tid, \%Tree, $LibVersion);
9987
9988 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9989 {
9990 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9991 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9992 {
9993 $Delete{$Tid} = 1;
9994 last;
9995 }
9996 }
9997 }
9998 else
9999 {
10000 # remove type
10001 delete($TypeInfo{$LibVersion}{$Tid});
10002 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010003 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010004
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010005 if($Kind eq "Extra")
10006 { # remove duplicates
10007 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
10008 {
10009 if($UsedType{$Tid})
10010 { # All & Extended
10011 next;
10012 }
10013
10014 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10015
10016 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
10017 delete($TypeInfo{$LibVersion}{$Tid});
10018 }
10019 }
10020 }
10021
10022 foreach my $Tid (keys(%Delete))
10023 {
10024 delete($TypeInfo{$LibVersion}{$Tid});
10025 }
10026}
10027
10028sub check_Completeness($$)
10029{
10030 my ($Info, $LibVersion) = @_;
10031
10032 # data types
10033 if(defined $Info->{"Memb"})
10034 {
10035 foreach my $Pos (keys(%{$Info->{"Memb"}}))
10036 {
10037 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
10038 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
10039 }
10040 }
10041 }
10042 if(defined $Info->{"Base"})
10043 {
10044 foreach my $Bid (keys(%{$Info->{"Base"}})) {
10045 check_TypeInfo($Bid, $LibVersion);
10046 }
10047 }
10048 if(defined $Info->{"BaseType"}) {
10049 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
10050 }
10051 if(defined $Info->{"TParam"})
10052 {
10053 foreach my $Pos (keys(%{$Info->{"TParam"}}))
10054 {
10055 my $TName = $Info->{"TParam"}{$Pos}{"name"};
10056 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
10057 next;
10058 }
10059 if($TName eq "_BoolType") {
10060 next;
10061 }
10062 if($TName=~/\Asizeof\(/) {
10063 next;
10064 }
10065 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10066 check_TypeInfo($Tid, $LibVersion);
10067 }
10068 else
10069 {
10070 if(defined $Debug) {
10071 printMsg("WARNING", "missed type $TName");
10072 }
10073 }
10074 }
10075 }
10076
10077 # symbols
10078 if(defined $Info->{"Param"})
10079 {
10080 foreach my $Pos (keys(%{$Info->{"Param"}}))
10081 {
10082 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10083 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10084 }
10085 }
10086 }
10087 if(defined $Info->{"Return"}) {
10088 check_TypeInfo($Info->{"Return"}, $LibVersion);
10089 }
10090 if(defined $Info->{"Class"}) {
10091 check_TypeInfo($Info->{"Class"}, $LibVersion);
10092 }
10093}
10094
10095sub check_TypeInfo($$)
10096{
10097 my ($Tid, $LibVersion) = @_;
10098
10099 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10100 return;
10101 }
10102 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10103
10104 if(defined $TypeInfo{$LibVersion}{$Tid})
10105 {
10106 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10107 printMsg("ERROR", "missed type name ($Tid)");
10108 }
10109 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10110 }
10111 else {
10112 printMsg("ERROR", "missed type id $Tid");
10113 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010114}
10115
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010116sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010117{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010118 my ($TypeId, $LibVersion) = @_;
10119 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010120 if($Type{"Type"} eq "Typedef")
10121 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010122 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010123 if($Base{"Type"}=~/Class|Struct/)
10124 {
10125 if($Type{"Name"} eq $Base{"Name"}) {
10126 return 1;
10127 }
10128 elsif($Type{"Name"}=~/::(\w+)\Z/)
10129 {
10130 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10131 { # QPointer<QWidget>::QPointer
10132 return 1;
10133 }
10134 }
10135 }
10136 }
10137 return 0;
10138}
10139
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010140sub addExtension($)
10141{
10142 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010143 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010144 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010145 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010146 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010147 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10148 $TName=~s/\A(struct|union|class|enum) //;
10149 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010150
10151 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10152 "Header" => "extended.h",
10153 "ShortName" => $Symbol,
10154 "MnglName" => $Symbol,
10155 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10156 );
10157
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010158 $ExtendedSymbols{$Symbol} = 1;
10159 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10160 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010161 }
10162 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010163 $ExtendedSymbols{"external_func_0"} = 1;
10164 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10165 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010166}
10167
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010168sub findMethod($$$)
10169{
10170 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010171 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010172 {
10173 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10174 return $VirtMethodInClass;
10175 }
10176 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10177 return $VirtMethodInBaseClasses;
10178 }
10179 }
10180 return "";
10181}
10182
10183sub findMethod_Class($$$)
10184{
10185 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010186 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010187 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10188 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10189 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10190 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10191 { # search for interface with the same parameters suffix (overridden)
10192 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10193 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010194 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10195 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010196 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10197 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010198 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10199 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10200 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10201 return $Candidate;
10202 }
10203 }
10204 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010205 else
10206 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010207 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10208 return $Candidate;
10209 }
10210 }
10211 }
10212 }
10213 return "";
10214}
10215
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010216sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010217{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010218 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010219 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010220 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010221 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10222 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010223 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010224 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010225 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010226 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10227 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010228 { # pure virtual D2-destructors are marked as "virt" in the dump
10229 # virtual D2-destructors are NOT marked as "virt" in the dump
10230 # both destructors are not presented in the v-table
10231 next;
10232 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010233 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010234 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10235 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010236 }
10237}
10238
10239sub registerOverriding($)
10240{
10241 my $LibVersion = $_[0];
10242 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010243 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010244 foreach my $ClassName (@Classes)
10245 {
10246 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10247 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010248 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10249 { # pure virtuals
10250 next;
10251 }
10252 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10253 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010254 {
10255 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10256 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10257 { # both overridden virtual methods
10258 # and implemented pure virtual methods
10259 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10260 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10261 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010263 }
10264 }
10265 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10266 delete($VirtualTable{$LibVersion}{$ClassName});
10267 }
10268 }
10269}
10270
10271sub setVirtFuncPositions($)
10272{
10273 my $LibVersion = $_[0];
10274 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10275 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010276 my ($Num, $Rel) = (1, 0);
10277
10278 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010279 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010280 if($UsedDump{$LibVersion}{"DWARF"}) {
10281 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10282 }
10283 else {
10284 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10285 }
10286 foreach my $VirtFunc (@Funcs)
10287 {
10288 if($UsedDump{$LibVersion}{"DWARF"}) {
10289 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10290 }
10291 else {
10292 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10293 }
10294
10295 # set relative positions
10296 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10297 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10298 { # relative position excluding added and removed virtual functions
10299 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10300 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10301 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10302 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010303 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010305 }
10306 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010307 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010308 {
10309 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010310 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010311 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010312 }
10313 }
10314}
10315
10316sub get_sub_classes($$$)
10317{
10318 my ($ClassId, $LibVersion, $Recursive) = @_;
10319 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10320 my @Subs = ();
10321 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10322 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010323 if($Recursive)
10324 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010325 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10326 push(@Subs, $SubSubId);
10327 }
10328 }
10329 push(@Subs, $SubId);
10330 }
10331 return @Subs;
10332}
10333
10334sub get_base_classes($$$)
10335{
10336 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010337 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010338 return () if(not defined $ClassType{"Base"});
10339 my @Bases = ();
10340 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10341 keys(%{$ClassType{"Base"}}))
10342 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010343 if($Recursive)
10344 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010345 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10346 push(@Bases, $SubBaseId);
10347 }
10348 }
10349 push(@Bases, $BaseId);
10350 }
10351 return @Bases;
10352}
10353
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010354sub getVTable_Model($$)
10355{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010356 my ($ClassId, $LibVersion) = @_;
10357 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10358 my @Elements = ();
10359 foreach my $BaseId (@Bases, $ClassId)
10360 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010361 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010362 {
10363 if(defined $VirtualTable{$LibVersion}{$BName})
10364 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010365 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10366 if($UsedDump{$LibVersion}{"DWARF"}) {
10367 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10368 }
10369 else {
10370 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10371 }
10372 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010373 push(@Elements, $VFunc);
10374 }
10375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010376 }
10377 }
10378 return @Elements;
10379}
10380
10381sub getVShift($$)
10382{
10383 my ($ClassId, $LibVersion) = @_;
10384 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10385 my $VShift = 0;
10386 foreach my $BaseId (@Bases)
10387 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010388 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010389 {
10390 if(defined $VirtualTable{$LibVersion}{$BName}) {
10391 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10392 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010393 }
10394 }
10395 return $VShift;
10396}
10397
10398sub getShift($$)
10399{
10400 my ($ClassId, $LibVersion) = @_;
10401 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10402 my $Shift = 0;
10403 foreach my $BaseId (@Bases)
10404 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010405 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010406 {
10407 if($Size!=1)
10408 { # not empty base class
10409 $Shift+=$Size;
10410 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010411 }
10412 }
10413 return $Shift;
10414}
10415
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010416sub getVTable_Size($$)
10417{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010418 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010419 my $Size = 0;
10420 # three approaches
10421 if(not $Size)
10422 { # real size
10423 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10424 $Size = keys(%VTable);
10425 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010426 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010427 if(not $Size)
10428 { # shared library symbol size
10429 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10430 $Size /= $WORD_SIZE{$LibVersion};
10431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010432 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010433 if(not $Size)
10434 { # model size
10435 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10436 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10437 }
10438 }
10439 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010440}
10441
10442sub isCopyingClass($$)
10443{
10444 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010445 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010446}
10447
10448sub isLeafClass($$)
10449{
10450 my ($ClassId, $LibVersion) = @_;
10451 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10452}
10453
10454sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010455{ # check structured type for public fields
10456 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010457}
10458
10459sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010460{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010461 my ($TypePtr, $Skip, $Start, $End) = @_;
10462 return 0 if(not $TypePtr);
10463 if($End==-1) {
10464 $End = keys(%{$TypePtr->{"Memb"}})-1;
10465 }
10466 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10467 {
10468 if($Skip and $Skip->{$MemPos})
10469 { # skip removed/added fields
10470 next;
10471 }
10472 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10473 {
10474 if(isPublic($TypePtr, $MemPos)) {
10475 return ($MemPos+1);
10476 }
10477 }
10478 }
10479 return 0;
10480}
10481
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010482sub isReserved($)
10483{ # reserved fields == private
10484 my $MName = $_[0];
10485 if($MName=~/reserved|padding|f_spare/i) {
10486 return 1;
10487 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010488 if($MName=~/\A[_]*(spare|pad|unused)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010489 return 1;
10490 }
10491 if($MName=~/(pad\d+)/i) {
10492 return 1;
10493 }
10494 return 0;
10495}
10496
10497sub isPublic($$)
10498{
10499 my ($TypePtr, $FieldPos) = @_;
10500 return 0 if(not $TypePtr);
10501 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10502 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10503 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10504 { # by name in C language
10505 # FIXME: add other methods to detect private members
10506 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10507 if($MName=~/priv|abidata|parent_object/i)
10508 { # C-styled private data
10509 return 0;
10510 }
10511 if(lc($MName) eq "abi")
10512 { # ABI information/reserved field
10513 return 0;
10514 }
10515 if(isReserved($MName))
10516 { # reserved fields
10517 return 0;
10518 }
10519 return 1;
10520 }
10521 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10522 { # by access in C++ language
10523 return 1;
10524 }
10525 return 0;
10526}
10527
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010528sub getVTable_Real($$)
10529{
10530 my ($ClassName, $LibVersion) = @_;
10531 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10532 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010533 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010534 if(defined $Type{"VTable"}) {
10535 return %{$Type{"VTable"}};
10536 }
10537 }
10538 return ();
10539}
10540
10541sub cmpVTables($)
10542{
10543 my $ClassName = $_[0];
10544 my $Res = cmpVTables_Real($ClassName, 1);
10545 if($Res==-1) {
10546 $Res = cmpVTables_Model($ClassName);
10547 }
10548 return $Res;
10549}
10550
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010551sub cmpVTables_Model($)
10552{
10553 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010554 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010555 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010556 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010557 return 1;
10558 }
10559 }
10560 return 0;
10561}
10562
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010563sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010564{
10565 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010566 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10567 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010568 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010569 my %VTable_Old = getVTable_Real($ClassName, 1);
10570 my %VTable_New = getVTable_Real($ClassName, 2);
10571 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010572 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010573 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010574 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010575 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010576 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10577 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010578 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010579 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010580 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010581 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010582 my $Entry1 = $VTable_Old{$Offset};
10583 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010584 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010585 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010586 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010587 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010588 $Entry1 = simpleVEntry($Entry1);
10589 $Entry2 = simpleVEntry($Entry2);
10590 if($Entry1 ne $Entry2)
10591 { # register as changed
10592 if($Entry1=~/::([^:]+)\Z/)
10593 {
10594 my $M1 = $1;
10595 if($Entry2=~/::([^:]+)\Z/)
10596 {
10597 my $M2 = $1;
10598 if($M1 eq $M2)
10599 { # overridden
10600 next;
10601 }
10602 }
10603 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010604 if(differentDumps("G"))
10605 {
10606 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10607 {
10608 # GCC 4.6.1: -0x00000000000000010
10609 # GCC 4.7.0: -16
10610 next;
10611 }
10612 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010613 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010614 }
10615 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010616 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010617}
10618
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010619sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010620{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010621 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010622 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10623 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010624 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010625 { # already registered
10626 next;
10627 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010628 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010629 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010630 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010631 foreach my $Symbol (@Affected)
10632 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010633 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010634 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010635 "Target"=>$ClassName);
10636 }
10637 }
10638 }
10639}
10640
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010641sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010642{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010643 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010644 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010645 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010646 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010647 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010648 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010649 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010650 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010651 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010652 if($TName_Tid{1}{$ClassName}
10653 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010654 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010655 if(defined $CompleteSignature{1}{$Symbol}
10656 and $CompleteSignature{1}{$Symbol}{"Virt"})
10657 { # override some method in v.1
10658 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010659 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010660 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010661 }
10662 }
10663 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010664 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010665 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010666 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010667 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010668 if($TName_Tid{2}{$ClassName}
10669 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010670 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010671 if(defined $CompleteSignature{2}{$Symbol}
10672 and $CompleteSignature{2}{$Symbol}{"Virt"})
10673 { # override some method in v.2
10674 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010675 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010676 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010677 }
10678 }
10679 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010680 if($Level eq "Binary")
10681 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010682 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010683 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10684 { # check replacements, including pure virtual methods
10685 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10686 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010687 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010688 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10689 if($AddedPos==$RemovedPos)
10690 {
10691 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10692 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10693 last; # other methods will be reported as "added" or "removed"
10694 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010695 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010696 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10697 {
10698 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10699 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010700 next;
10701 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010702 my $ProblemType = "Virtual_Replacement";
10703 my @Affected = ($RemovedVFunc);
10704 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10705 { # pure methods
10706 if(not isUsedClass($ClassId, 1, $Level))
10707 { # not a parameter of some exported method
10708 next;
10709 }
10710 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010711
10712 # affected all methods (both virtual and non-virtual ones)
10713 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10714 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010715 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010716 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010717 foreach my $AffectedInt (@Affected)
10718 {
10719 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10720 { # affected exported methods only
10721 next;
10722 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010723 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10724 next;
10725 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010726 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10727 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010728 "Target"=>get_Signature($AddedVFunc, 2),
10729 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10730 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010731 }
10732 }
10733 }
10734 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010735 if(not checkDump(1, "2.0")
10736 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010737 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010738 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010739 return;
10740 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010741 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010742 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010743 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010744 next if(not $ClassId_Old);
10745 if(not isCreatable($ClassId_Old, 1))
10746 { # skip classes without public constructors (including auto-generated)
10747 # example: class has only a private exported or private inline constructor
10748 next;
10749 }
10750 if($ClassName=~/>/)
10751 { # skip affected template instances
10752 next;
10753 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010754 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010755 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010756 if(not $ClassId_New) {
10757 next;
10758 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010759 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010760 if($Class_New{"Type"}!~/Class|Struct/)
10761 { # became typedef
10762 if($Level eq "Binary") {
10763 next;
10764 }
10765 if($Level eq "Source")
10766 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010767 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010768 if($Class_New{"Type"}!~/Class|Struct/) {
10769 next;
10770 }
10771 $ClassId_New = $Class_New{"Tid"};
10772 }
10773 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010774 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10775 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 +040010776
10777 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10778 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10779
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010780 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010781 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10782 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010783 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10784 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010785 my $Shift_Old = getShift($ClassId_Old, 1);
10786 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010787 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010788 my ($Added, $Removed) = (0, 0);
10789 my @StableBases_Old = ();
10790 foreach my $BaseId (@Bases_Old)
10791 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010792 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010793 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010794 push(@StableBases_Old, $BaseId);
10795 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010796 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010797 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010798 { # removed base
10799 # excluding namespace::SomeClass to SomeClass renaming
10800 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010801 if($Level eq "Binary")
10802 { # Binary-level
10803 if($Shift_Old ne $Shift_New)
10804 { # affected fields
10805 if(havePubFields(\%Class_Old)) {
10806 $ProblemKind .= "_And_Shift";
10807 }
10808 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10809 $ProblemKind .= "_And_Size";
10810 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010811 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010812 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10813 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010814 { # affected v-table
10815 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010816 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010817 }
10818 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010819 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010820 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10821 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010822 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10823 {
10824 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10825 if($ProblemKind=~/VTable/) {
10826 $VTableChanged_M{$SubName}=1;
10827 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010828 }
10829 }
10830 foreach my $Interface (@Affected)
10831 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010832 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10833 next;
10834 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010835 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010836 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010837 "Target"=>$BaseName,
10838 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10839 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10840 "Shift"=>abs($Shift_New-$Shift_Old) );
10841 }
10842 $Removed+=1;
10843 }
10844 }
10845 my @StableBases_New = ();
10846 foreach my $BaseId (@Bases_New)
10847 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010848 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010849 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010850 push(@StableBases_New, $BaseId);
10851 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010852 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010853 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010854 { # added base
10855 # excluding namespace::SomeClass to SomeClass renaming
10856 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010857 if($Level eq "Binary")
10858 { # Binary-level
10859 if($Shift_Old ne $Shift_New)
10860 { # affected fields
10861 if(havePubFields(\%Class_Old)) {
10862 $ProblemKind .= "_And_Shift";
10863 }
10864 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10865 $ProblemKind .= "_And_Size";
10866 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010867 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010868 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10869 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010870 { # affected v-table
10871 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010872 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010873 }
10874 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010875 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010876 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10877 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010878 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10879 {
10880 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10881 if($ProblemKind=~/VTable/) {
10882 $VTableChanged_M{$SubName}=1;
10883 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010884 }
10885 }
10886 foreach my $Interface (@Affected)
10887 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010888 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10889 next;
10890 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010891 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010892 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010893 "Target"=>$BaseName,
10894 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10895 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10896 "Shift"=>abs($Shift_New-$Shift_Old) );
10897 }
10898 $Added+=1;
10899 }
10900 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010901 if($Level eq "Binary")
10902 { # Binary-level
10903 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010904 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10905 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010906 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010907 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010908 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010909 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010910 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010911 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10912 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010913 if($NewPos!=$OldPos)
10914 { # changed position of the base class
10915 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010916 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010917 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10918 next;
10919 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010920 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10921 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010922 "Target"=>$BaseName,
10923 "Old_Value"=>$OldPos-1,
10924 "New_Value"=>$NewPos-1 );
10925 }
10926 }
10927 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10928 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10929 { # became non-virtual base
10930 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10931 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010932 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10933 next;
10934 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010935 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10936 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010937 "Target"=>$BaseName );
10938 }
10939 }
10940 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10941 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10942 { # became virtual base
10943 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10944 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010945 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10946 next;
10947 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010948 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10949 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010950 "Target"=>$BaseName );
10951 }
10952 }
10953 }
10954 }
10955 # detect size changes in base classes
10956 if($Shift_Old!=$Shift_New)
10957 { # size of allocable class
10958 foreach my $BaseId (@StableBases_Old)
10959 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010960 my %BaseType = get_Type($BaseId, 1);
10961 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010962 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010963 if($Size_Old ne $Size_New
10964 and $Size_Old and $Size_New)
10965 {
10966 my $ProblemType = "";
10967 if(isCopyingClass($BaseId, 1)) {
10968 $ProblemType = "Size_Of_Copying_Class";
10969 }
10970 elsif($AllocableClass{1}{$BaseType{"Name"}})
10971 {
10972 if($Size_New>$Size_Old)
10973 { # increased size
10974 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010975 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010976 else
10977 { # decreased size
10978 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10979 if(not havePubFields(\%Class_Old))
10980 { # affected class has no public members
10981 next;
10982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010983 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010984 }
10985 next if(not $ProblemType);
10986 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10987 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010988 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10989 next;
10990 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010991 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10992 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010993 "Target"=>$BaseType{"Name"},
10994 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10995 "New_Size"=>$Size_New*$BYTE_SIZE );
10996 }
10997 }
10998 }
10999 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011000 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011001 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011002 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011003 { # compare virtual tables size in base classes
11004 my $VShift_Old = getVShift($ClassId_Old, 1);
11005 my $VShift_New = getVShift($ClassId_New, 2);
11006 if($VShift_Old ne $VShift_New)
11007 { # changes in the base class or changes in the list of base classes
11008 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
11009 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
11010 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011011 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011012 foreach my $BaseId (@AllBases_Old)
11013 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011014 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011015 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011016 { # lost base
11017 next;
11018 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011019 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
11020 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011021 if($VSize_Old!=$VSize_New)
11022 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011023 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011024 { # TODO: affected non-virtual methods?
11025 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011026 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
11027 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011028 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011029 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011030 { # skip interfaces that have not changed the absolute virtual position
11031 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011032 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011033 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
11034 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011035 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011036 $VTableChanged_M{$BaseType{"Name"}} = 1;
11037 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011038 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11039 { # the reason of the layout change: added virtual functions
11040 next if($VirtualReplacement{$VirtFunc});
11041 my $ProblemType = "Added_Virtual_Method";
11042 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11043 $ProblemType = "Added_Pure_Virtual_Method";
11044 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011045 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011046 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011047 "Target"=>get_Signature($VirtFunc, 2) );
11048 }
11049 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11050 { # the reason of the layout change: removed virtual functions
11051 next if($VirtualReplacement{$VirtFunc});
11052 my $ProblemType = "Removed_Virtual_Method";
11053 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11054 $ProblemType = "Removed_Pure_Virtual_Method";
11055 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011056 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011057 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011058 "Target"=>get_Signature($VirtFunc, 1) );
11059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011060 }
11061 }
11062 }
11063 }
11064 }
11065 }
11066 }
11067}
11068
11069sub isCreatable($$)
11070{
11071 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011072 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011073 or isCopyingClass($ClassId, $LibVersion)) {
11074 return 1;
11075 }
11076 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11077 { # Fix for incomplete data: if this class has
11078 # a base class then it should also has a constructor
11079 return 1;
11080 }
11081 if($ReturnedClass{$LibVersion}{$ClassId})
11082 { # returned by some method of this class
11083 # or any other class
11084 return 1;
11085 }
11086 return 0;
11087}
11088
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011089sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011090{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011091 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011092 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11093 { # parameter of some exported method
11094 return 1;
11095 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011096 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11097 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011098 { # method from target class
11099 return 1;
11100 }
11101 return 0;
11102}
11103
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011104sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011105{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011106 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011107 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011108 # - virtual
11109 # - pure-virtual
11110 # - non-virtual
11111 if($CompleteSignature{1}{$Interface}{"Data"})
11112 { # global data is not affected
11113 return;
11114 }
11115 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011116 if(not $Class_Id) {
11117 return;
11118 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011119 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011120 if(cmpVTables_Real($CName, 1)==0)
11121 { # no changes
11122 return;
11123 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011124 $CheckedTypes{$Level}{$CName} = 1;
11125 if($Level eq "Binary")
11126 { # Binary-level
11127 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11128 and not isUsedClass($Class_Id, 1, $Level))
11129 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011130 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011131 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011132 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011133 }
11134 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11135 {
11136 if(defined $VirtualTable{2}{$CName}{$Func}
11137 and defined $CompleteSignature{2}{$Func})
11138 {
11139 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11140 and $CompleteSignature{2}{$Func}{"PureVirt"})
11141 { # became pure virtual
11142 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11143 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011144 "Target"=>get_Signature_M($Func, 1) );
11145 $VTableChanged_M{$CName} = 1;
11146 }
11147 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11148 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11149 { # became non-pure virtual
11150 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11151 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011152 "Target"=>get_Signature_M($Func, 1) );
11153 $VTableChanged_M{$CName} = 1;
11154 }
11155 }
11156 }
11157 if($Level eq "Binary")
11158 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011159 # check virtual table structure
11160 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11161 {
11162 next if($Interface eq $AddedVFunc);
11163 next if($VirtualReplacement{$AddedVFunc});
11164 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11165 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11166 { # pure virtual methods affect all others (virtual and non-virtual)
11167 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011168 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011169 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011170 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011171 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011172 elsif(not defined $VirtualTable{1}{$CName}
11173 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011174 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011175 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011176 { # became polymorphous class, added v-table pointer
11177 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011178 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011179 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011180 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011181 }
11182 else
11183 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011184 my $VSize_Old = getVTable_Size($CName, 1);
11185 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011186 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011187 if(isCopyingClass($Class_Id, 1))
11188 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11189 my $ProblemType = "Added_Virtual_Method";
11190 if(isLeafClass($Class_Id, 1)) {
11191 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11192 }
11193 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11194 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011195 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011196 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011197 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011198 else
11199 {
11200 my $ProblemType = "Added_Virtual_Method";
11201 if(isLeafClass($Class_Id, 1)) {
11202 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11203 }
11204 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11205 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011206 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011207 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011208 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011209 }
11210 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011211 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11212 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011213 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011214 if(defined $VirtualTable{1}{$CName}
11215 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011216 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011217 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11218 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011219
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011220 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011221 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011222 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11223 foreach my $ASymbol (@Affected)
11224 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011225 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11226 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011227 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011228 next;
11229 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011230 }
11231 $CheckedSymbols{$Level}{$ASymbol} = 1;
11232 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11233 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011234 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011235 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011236 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011238 }
11239 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011240 else {
11241 # safe
11242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011243 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011244 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11245 {
11246 next if($VirtualReplacement{$RemovedVFunc});
11247 if($RemovedVFunc eq $Interface
11248 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11249 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011250 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011251 next;
11252 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011253 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011254 { # became non-polymorphous class, removed v-table pointer
11255 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11256 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011257 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011258 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011259 }
11260 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11261 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11262 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011263 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011264 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011265 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11266 next;
11267 }
11268 my $VPos_New = -1;
11269 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011270 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011271 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11272 }
11273 else
11274 {
11275 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011276 next;
11277 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011278 }
11279 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11280 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11281 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11282 {
11283 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11284 foreach my $ASymbol (@Affected)
11285 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011286 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11287 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011288 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011289 next;
11290 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011291 }
11292 my $ProblemType = "Removed_Virtual_Method";
11293 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11294 $ProblemType = "Removed_Pure_Virtual_Method";
11295 }
11296 $CheckedSymbols{$Level}{$ASymbol} = 1;
11297 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11298 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011299 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011300 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011301 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011302 }
11303 }
11304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011305 }
11306 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011307 else
11308 { # Source-level
11309 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011310 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011311 next if($Interface eq $AddedVFunc);
11312 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011313 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011314 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11315 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011316 "Target"=>get_Signature($AddedVFunc, 2) );
11317 }
11318 }
11319 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11320 {
11321 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11322 {
11323 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11324 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011325 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011326 }
11327 }
11328 }
11329}
11330
11331sub find_MemberPair_Pos_byName($$)
11332{
11333 my ($Member_Name, $Pair_Type) = @_;
11334 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11335 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11336 {
11337 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11338 {
11339 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11340 $Name=~s/\A[_]+|[_]+\Z//g;
11341 if($Name eq $Member_Name) {
11342 return $MemberPair_Pos;
11343 }
11344 }
11345 }
11346 return "lost";
11347}
11348
11349sub find_MemberPair_Pos_byVal($$)
11350{
11351 my ($Member_Value, $Pair_Type) = @_;
11352 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11353 {
11354 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11355 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11356 return $MemberPair_Pos;
11357 }
11358 }
11359 return "lost";
11360}
11361
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011362my %Severity_Val=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011363 "High"=>3,
11364 "Medium"=>2,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011365 "Low"=>1,
11366 "Safe"=>-1
11367);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011368
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011369sub cmpSeverities($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011370{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011371 my ($S1, $S2) = @_;
11372 if(not $S1) {
11373 return 0;
11374 }
11375 elsif(not $S2) {
11376 return 1;
11377 }
11378 return ($Severity_Val{$S1}>$Severity_Val{$S2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011379}
11380
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011381sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011382{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011383 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011384 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011385 if( $_->{"T1"} eq $_[0]
11386 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011387 {
11388 return 1;
11389 }
11390 }
11391 return 0;
11392}
11393
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011394sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011395{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011396 my %IDs = (
11397 "T1" => $_[0],
11398 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011399 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011400 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011401}
11402
11403sub isRenamed($$$$$)
11404{
11405 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11406 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11407 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011408 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011409 if(not defined $Type2->{"Memb"}{$MemPos}) {
11410 return "";
11411 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011412 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011413 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011414
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011415 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11416 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011417 if($MemberPair_Pos_Rev eq "lost")
11418 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011419 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11420 { # base type match
11421 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011422 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011423 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11424 { # exact type match
11425 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011426 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011427 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11428 { # size match
11429 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011430 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011431 if(isReserved($Pair_Name))
11432 { # reserved fields
11433 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011434 }
11435 }
11436 return "";
11437}
11438
11439sub isLastElem($$)
11440{
11441 my ($Pos, $TypeRef) = @_;
11442 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11443 if($Name=~/last|count|max|total/i)
11444 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11445 return 1;
11446 }
11447 elsif($Name=~/END|NLIMITS\Z/)
11448 { # __RLIMIT_NLIMITS
11449 return 1;
11450 }
11451 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11452 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11453 { # NImageFormats, NColorRoles
11454 return 1;
11455 }
11456 return 0;
11457}
11458
11459sub nonComparable($$)
11460{
11461 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011462
11463 my $N1 = $T1->{"Name"};
11464 my $N2 = $T2->{"Name"};
11465
11466 $N1=~s/\A(struct|union|enum) //;
11467 $N2=~s/\A(struct|union|enum) //;
11468
11469 if($N1 ne $N2
11470 and not isAnon($N1)
11471 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011472 { # different names
11473 if($T1->{"Type"} ne "Pointer"
11474 or $T2->{"Type"} ne "Pointer")
11475 { # compare base types
11476 return 1;
11477 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011478 if($N1!~/\Avoid\s*\*/
11479 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011480 {
11481 return 1;
11482 }
11483 }
11484 elsif($T1->{"Type"} ne $T2->{"Type"})
11485 { # different types
11486 if($T1->{"Type"} eq "Class"
11487 and $T2->{"Type"} eq "Struct")
11488 { # "class" to "struct"
11489 return 0;
11490 }
11491 elsif($T2->{"Type"} eq "Class"
11492 and $T1->{"Type"} eq "Struct")
11493 { # "struct" to "class"
11494 return 0;
11495 }
11496 else
11497 { # "class" to "enum"
11498 # "union" to "class"
11499 # ...
11500 return 1;
11501 }
11502 }
11503 return 0;
11504}
11505
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011506sub isOpaque($)
11507{
11508 my $T = $_[0];
11509 if(not defined $T->{"Memb"})
11510 {
11511 return 1;
11512 }
11513 return 0;
11514}
11515
11516sub removeVPtr($)
11517{ # support for old ABI dumps
11518 my $TPtr = $_[0];
11519 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11520 if($#Pos>=1)
11521 {
11522 foreach my $Pos (0 .. $#Pos-1)
11523 {
11524 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11525 }
11526 delete($TPtr->{"Memb"}{$#Pos});
11527 }
11528}
11529
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011530sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011531{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011532 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011533 return {} if(not $Type1_Id or not $Type2_Id);
11534
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011535 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011536 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011537 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011538 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011539
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011540 my %Type1 = get_Type($Type1_Id, 1);
11541 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011542 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011543 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011544 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011545
11546 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011547 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11548 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011549
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011550 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11551
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011552 my %SubProblems = ();
11553
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011554 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11555 {
11556 if($Type1_Pure{"Type"}=~/Struct|Union/
11557 and $Type2_Pure{"Type"}=~/Struct|Union/)
11558 {
11559 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11560 {
11561 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11562 "Target"=>$Type1_Pure{"Name"},
11563 "Type_Name"=>$Type1_Pure{"Name"} );
11564
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011565 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011566 }
11567 }
11568 }
11569
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011570 if(not $Type1_Pure{"Size"}
11571 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011572 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011573 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11574 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11575 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011576 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011577 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011578 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011579 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011580 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011581 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011582 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011583 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11584 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11585 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011586
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011587 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11588 { # support for old ABI dumps
11589 # _vptr field added in 3.0
11590 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11591 {
11592 if(defined $Type2_Pure{"Memb"}
11593 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11594 {
11595 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11596 delete($Type2_Pure{"Memb"}{0});
11597 }
11598 else {
11599 removeVPtr(\%Type2_Pure);
11600 }
11601 }
11602 }
11603 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11604 {
11605 if(defined $Type1_Pure{"Memb"}
11606 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11607 {
11608 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11609 delete($Type1_Pure{"Memb"}{0});
11610 }
11611 else {
11612 removeVPtr(\%Type1_Pure);
11613 }
11614 }
11615 }
11616 }
11617
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011618 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11619 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011620
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011621 if(not $UseOldDumps and %Typedef_1 and %Typedef_2
11622 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11623 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011624 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011625 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11626 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011627 if($Base_1{"Name"} ne $Base_2{"Name"})
11628 {
11629 if(differentDumps("G")
11630 or differentDumps("V"))
11631 { # different GCC versions or different dumps
11632 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11633 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11634 # std::__va_list and __va_list
11635 $Base_1{"Name"}=~s/\A(\w+::)+//;
11636 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011637 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11638 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011639 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011640 }
11641 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11642 and $Base_1{"Name"} ne $Base_2{"Name"})
11643 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011644 if($Level eq "Binary"
11645 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011646 {
11647 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11648 "Target"=>$Typedef_1{"Name"},
11649 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011650 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11651 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11652 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011653 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11654 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011655 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011656 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011657 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11658 {
11659 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11660 "Target"=>$Typedef_1{"Name"},
11661 "Type_Name"=>$Typedef_1{"Name"},
11662 "Old_Value"=>$Base_1{"Name"},
11663 "New_Value"=>$Base_2{"Name"} );
11664 }
11665 else
11666 {
11667 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11668 "Target"=>$Typedef_1{"Name"},
11669 "Type_Name"=>$Typedef_1{"Name"},
11670 "Old_Value"=>$Base_1{"Name"},
11671 "New_Value"=>$Base_2{"Name"} );
11672 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011674 }
11675 }
11676 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11677 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011678 my $TT1 = $Type1_Pure{"Type"};
11679 my $TT2 = $Type2_Pure{"Type"};
11680
11681 if($TT1 ne $TT2
11682 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011683 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011684 my $Short1 = $Type1_Pure{"Name"};
11685 my $Short2 = $Type2_Pure{"Name"};
11686
11687 $Short1=~s/\A\Q$TT1\E //ig;
11688 $Short2=~s/\A\Q$TT2\E //ig;
11689
11690 if($Short1 eq $Short2)
11691 {
11692 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11693 "Target"=>$Type1_Pure{"Name"},
11694 "Type_Name"=>$Type1_Pure{"Name"},
11695 "Old_Value"=>lc($Type1_Pure{"Type"}),
11696 "New_Value"=>lc($Type2_Pure{"Type"}) );
11697 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011698 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011699 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011700 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011701 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011702 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11703 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11704 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11705 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011706 if($Level eq "Binary"
11707 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011708 {
11709 my $ProblemKind = "DataType_Size";
11710 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011711 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011712 {
11713 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11714 $ProblemKind = "Size_Of_Copying_Class";
11715 }
11716 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11717 {
11718 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11719 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11720 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011721 else
11722 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011723 # descreased size of allocable class
11724 # it has no special effects
11725 }
11726 }
11727 }
11728 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11729 "Target"=>$Type1_Pure{"Name"},
11730 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011731 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011732 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011733 }
11734 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011735 if(defined $Type1_Pure{"BaseType"}
11736 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011737 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011738 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11739 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011740 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011741 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11742 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011743 }
11744 }
11745 }
11746 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11747 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11748 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11749 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11750 { # detect removed and renamed fields
11751 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11752 next if(not $Member_Name);
11753 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);
11754 if($MemberPair_Pos eq "lost")
11755 {
11756 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11757 {
11758 if(isUnnamed($Member_Name))
11759 { # support for old-version dumps
11760 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011761 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011762 next;
11763 }
11764 }
11765 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11766 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011767 $RenamedField{$Member_Pos} = $RenamedTo;
11768 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011769 }
11770 else
11771 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011772 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011773 }
11774 }
11775 elsif($Type1_Pure{"Type"} eq "Enum")
11776 {
11777 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11778 next if($Member_Value1 eq "");
11779 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11780 if($MemberPair_Pos ne "lost")
11781 { # renamed
11782 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11783 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11784 if($MemberPair_Pos_Rev eq "lost")
11785 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011786 $RenamedField{$Member_Pos} = $RenamedTo;
11787 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011788 }
11789 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011790 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011791 }
11792 }
11793 else
11794 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011795 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011796 }
11797 }
11798 }
11799 else
11800 { # related
11801 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11802 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11803 }
11804 }
11805 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11806 { # detect added fields
11807 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11808 next if(not $Member_Name);
11809 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);
11810 if($MemberPair_Pos eq "lost")
11811 {
11812 if(isUnnamed($Member_Name))
11813 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011814 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011815 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011816 next;
11817 }
11818 }
11819 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11820 {
11821 if(not $RenamedField_Rev{$Member_Pos})
11822 { # added
11823 $AddedField{$Member_Pos}=1;
11824 }
11825 }
11826 }
11827 }
11828 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11829 { # detect moved fields
11830 my (%RelPos, %RelPosName, %AbsPos) = ();
11831 my $Pos = 0;
11832 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11833 { # relative positions in 1st version
11834 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11835 next if(not $Member_Name);
11836 if(not $RemovedField{$Member_Pos})
11837 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011838 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011839 $RelPosName{1}{$Pos} = $Member_Name;
11840 $AbsPos{1}{$Pos++} = $Member_Pos;
11841 }
11842 }
11843 $Pos = 0;
11844 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11845 { # relative positions in 2nd version
11846 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11847 next if(not $Member_Name);
11848 if(not $AddedField{$Member_Pos})
11849 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011850 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011851 $RelPosName{2}{$Pos} = $Member_Name;
11852 $AbsPos{2}{$Pos++} = $Member_Pos;
11853 }
11854 }
11855 foreach my $Member_Name (keys(%{$RelPos{1}}))
11856 {
11857 my $RPos1 = $RelPos{1}{$Member_Name};
11858 my $AbsPos1 = $NameToPosA{$Member_Name};
11859 my $Member_Name2 = $Member_Name;
11860 if(my $RenamedTo = $RenamedField{$AbsPos1})
11861 { # renamed
11862 $Member_Name2 = $RenamedTo;
11863 }
11864 my $RPos2 = $RelPos{2}{$Member_Name2};
11865 if($RPos2 ne "" and $RPos1 ne $RPos2)
11866 { # different relative positions
11867 my $AbsPos2 = $NameToPosB{$Member_Name2};
11868 if($AbsPos1 ne $AbsPos2)
11869 { # different absolute positions
11870 my $ProblemType = "Moved_Field";
11871 if(not isPublic(\%Type1_Pure, $AbsPos1))
11872 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011873 if($Level eq "Source") {
11874 next;
11875 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011876 $ProblemType = "Moved_Private_Field";
11877 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011878 if($Level eq "Binary"
11879 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011880 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011881 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011882 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011883 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011884 if($MemSize1 ne $MemSize2) {
11885 $ProblemType .= "_And_Size";
11886 }
11887 }
11888 if($ProblemType eq "Moved_Private_Field") {
11889 next;
11890 }
11891 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11892 "Target"=>$Member_Name,
11893 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011894 "Old_Value"=>$RPos1,
11895 "New_Value"=>$RPos2 );
11896 }
11897 }
11898 }
11899 }
11900 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011901 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011902 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11903 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011904 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011905 if(my $RenamedTo = $RenamedField{$Member_Pos})
11906 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011907 if(defined $Constants{2}{$Member_Name})
11908 {
11909 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11910 { # define OLD NEW
11911 next; # Safe
11912 }
11913 }
11914
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011915 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11916 {
11917 if(isPublic(\%Type1_Pure, $Member_Pos))
11918 {
11919 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11920 "Target"=>$Member_Name,
11921 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011922 "Old_Value"=>$Member_Name,
11923 "New_Value"=>$RenamedTo );
11924 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011925 elsif(isReserved($Member_Name))
11926 {
11927 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11928 "Target"=>$Member_Name,
11929 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011930 "Old_Value"=>$Member_Name,
11931 "New_Value"=>$RenamedTo );
11932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011933 }
11934 elsif($Type1_Pure{"Type"} eq "Enum")
11935 {
11936 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11937 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11938 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011939 "Old_Value"=>$Member_Name,
11940 "New_Value"=>$RenamedTo );
11941 }
11942 }
11943 elsif($RemovedField{$Member_Pos})
11944 { # removed
11945 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11946 {
11947 my $ProblemType = "Removed_Field";
11948 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011949 or isUnnamed($Member_Name))
11950 {
11951 if($Level eq "Source") {
11952 next;
11953 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011954 $ProblemType = "Removed_Private_Field";
11955 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011956 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011957 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011958 {
11959 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11960 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011961 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 +040011962 { # changed offset
11963 $ProblemType .= "_And_Layout";
11964 }
11965 }
11966 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11967 { # affected size
11968 $ProblemType .= "_And_Size";
11969 }
11970 }
11971 if($ProblemType eq "Removed_Private_Field") {
11972 next;
11973 }
11974 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11975 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011976 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011977 }
11978 elsif($Type2_Pure{"Type"} eq "Union")
11979 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011980 if($Level eq "Binary"
11981 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011982 {
11983 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11984 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011985 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011986 }
11987 else
11988 {
11989 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11990 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011991 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011992 }
11993 }
11994 elsif($Type1_Pure{"Type"} eq "Enum")
11995 {
11996 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11997 "Target"=>$Member_Name,
11998 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011999 "Old_Value"=>$Member_Name );
12000 }
12001 }
12002 else
12003 { # changed
12004 my $MemberPair_Pos = $RelatedField{$Member_Pos};
12005 if($Type1_Pure{"Type"} eq "Enum")
12006 {
12007 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12008 next if($Member_Value1 eq "");
12009 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12010 next if($Member_Value2 eq "");
12011 if($Member_Value1 ne $Member_Value2)
12012 {
12013 my $ProblemType = "Enum_Member_Value";
12014 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12015 $ProblemType = "Enum_Last_Member_Value";
12016 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012017 if($SkipConstants{1}{$Member_Name}) {
12018 $ProblemType = "Enum_Private_Member_Value";
12019 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012020 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12021 "Target"=>$Member_Name,
12022 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012023 "Old_Value"=>$Member_Value1,
12024 "New_Value"=>$Member_Value2 );
12025 }
12026 }
12027 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12028 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012029 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12030 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12031
12032 if($Access1 ne "private"
12033 and $Access2 eq "private")
12034 {
12035 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12036 "Target"=>$Member_Name,
12037 "Type_Name"=>$Type1_Pure{"Name"});
12038 }
12039 elsif($Access1 ne "protected"
12040 and $Access1 ne "private"
12041 and $Access2 eq "protected")
12042 {
12043 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12044 "Target"=>$Member_Name,
12045 "Type_Name"=>$Type1_Pure{"Name"});
12046 }
12047
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012048 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12049 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012050 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012051 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12052 $SizeV1 = $BSize1;
12053 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012054 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012055 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12056 $SizeV2 = $BSize2;
12057 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012058 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12059 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012060 if($Level eq "Binary"
12061 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012062 {
12063 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12064 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12065 { # field size change (including anon-structures and unions)
12066 # - same types
12067 # - unnamed types
12068 # - bitfields
12069 my $ProblemType = "Field_Size";
12070 if(not isPublic(\%Type1_Pure, $Member_Pos)
12071 or isUnnamed($Member_Name))
12072 { # should not be accessed by applications, goes to "Low Severity"
12073 # example: "abidata" members in GStreamer types
12074 $ProblemType = "Private_".$ProblemType;
12075 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012076 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 +040012077 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012078 if($Type2_Pure{"Type"} ne "Union"
12079 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012080 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012081 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 +040012082 { # changed offset
12083 $ProblemType .= "_And_Layout";
12084 }
12085 }
12086 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12087 $ProblemType .= "_And_Type_Size";
12088 }
12089 }
12090 if($ProblemType eq "Private_Field_Size")
12091 { # private field size with no effect
12092 $ProblemType = "";
12093 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012094 if($ProblemType eq "Field_Size")
12095 {
12096 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12097 { # Low severity
12098 $ProblemType = "Struct_Field_Size_Increased";
12099 }
12100 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012101 if($ProblemType)
12102 { # register a problem
12103 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12104 "Target"=>$Member_Name,
12105 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012106 "Old_Size"=>$SizeV1,
12107 "New_Size"=>$SizeV2);
12108 }
12109 }
12110 }
12111 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12112 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12113 { # do NOT check bitfield type changes
12114 next;
12115 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012116 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012117 {
12118 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12119 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12120 {
12121 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12122 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012123 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012124 }
12125 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12126 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12127 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012128 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012129 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012130 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012131 }
12132 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012133 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12134 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012135 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012136 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12137 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012138
12139 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012140 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012141 or $ProblemType eq "Field_Type_And_Size"
12142 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012143 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012144 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012145 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012146 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012147 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012148 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012149 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012150 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012151 }
12152 }
12153 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12154 {
12155 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012156 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012157 }
12158 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012159 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012160 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012161 }
12162 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12163 {
12164 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012165 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012166 }
12167 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012168 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012169 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012170 }
12171 }
12172 }
12173
12174 if($Level eq "Source")
12175 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012176 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012177 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012178 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12179 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012180
12181 if($ProblemType eq "Field_Type")
12182 {
12183 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012184 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012185 }
12186 }
12187 }
12188 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012189
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012190 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012191 {
12192 my $ProblemType_Init = $ProblemType;
12193 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012194 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012195 if(not isPublic(\%Type1_Pure, $Member_Pos)
12196 or isUnnamed($Member_Name)) {
12197 $ProblemType = "Private_".$ProblemType;
12198 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012199 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 +040012200 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012201 if($Type2_Pure{"Type"} ne "Union"
12202 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012203 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012204 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 +040012205 { # changed offset
12206 $ProblemType .= "_And_Layout";
12207 }
12208 }
12209 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12210 $ProblemType .= "_And_Type_Size";
12211 }
12212 }
12213 }
12214 else
12215 {
12216 if(not isPublic(\%Type1_Pure, $Member_Pos)
12217 or isUnnamed($Member_Name)) {
12218 next;
12219 }
12220 }
12221 if($ProblemType eq "Private_Field_Type_And_Size")
12222 { # private field change with no effect
12223 next;
12224 }
12225 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12226 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012227 "Type_Name"=>$Type1_Pure{"Name"});
12228
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012229 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012230 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012231 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012232 }
12233 }
12234 if(not isPublic(\%Type1_Pure, $Member_Pos))
12235 { # do NOT check internal type changes
12236 next;
12237 }
12238 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012239 { # checking member type changes
12240 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12241
12242 my %DupProblems = ();
12243
12244 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012245 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012246 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012247 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012248 if(not defined $AllAffected)
12249 {
12250 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12251 next;
12252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012253 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012254
12255 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12256 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12257
12258 if(not defined $AllAffected)
12259 {
12260 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012261 }
12262 }
12263 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012264
12265 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012266 }
12267 }
12268 }
12269 }
12270 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12271 { # checking added members, public and private
12272 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12273 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012274 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012275 if($AddedField{$Member_Pos})
12276 { # added
12277 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12278 {
12279 my $ProblemType = "Added_Field";
12280 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012281 or isUnnamed($Member_Name))
12282 {
12283 if($Level eq "Source") {
12284 next;
12285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012286 $ProblemType = "Added_Private_Field";
12287 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012288 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012289 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012290 {
12291 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12292 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012293 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 +040012294 { # changed offset
12295 $ProblemType .= "_And_Layout";
12296 }
12297 }
12298 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12299 $ProblemType .= "_And_Size";
12300 }
12301 }
12302 if($ProblemType eq "Added_Private_Field")
12303 { # skip added private fields
12304 next;
12305 }
12306 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12307 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012308 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012309 }
12310 elsif($Type2_Pure{"Type"} eq "Union")
12311 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012312 if($Level eq "Binary"
12313 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012314 {
12315 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12316 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012317 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012318 }
12319 else
12320 {
12321 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12322 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012323 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012324 }
12325 }
12326 elsif($Type2_Pure{"Type"} eq "Enum")
12327 {
12328 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12329 next if($Member_Value eq "");
12330 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12331 "Target"=>$Member_Name,
12332 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012333 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012334 }
12335 }
12336 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012337
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012338 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012339 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012340}
12341
12342sub isUnnamed($) {
12343 return $_[0]=~/\Aunnamed\d+\Z/;
12344}
12345
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012346sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012347{
12348 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012349 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12350 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12351 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12352 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012353 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012354 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012355 }
12356 return $TypeName;
12357}
12358
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012359sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012360{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012361 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012362 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012363 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12364 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012365 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012366 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12367 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012368 return () if(not $Type{"Type"});
12369 if($Type{"Type"} ne $Type_Type)
12370 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012371 return () if(not $Type{"BaseType"});
12372 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012373 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012374 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012375 return %Type;
12376}
12377
12378my %TypeSpecAttributes = (
12379 "Const" => 1,
12380 "Volatile" => 1,
12381 "ConstVolatile" => 1,
12382 "Restrict" => 1,
12383 "Typedef" => 1
12384);
12385
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012386sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012387{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012388 my ($TypeId, $Info) = @_;
12389 if(not $TypeId or not $Info
12390 or not $Info->{$TypeId}) {
12391 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012392 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012393 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12394 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12395 }
12396 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012397 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012398 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012399 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012400 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012401 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012402 return %Type;
12403}
12404
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012405sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012406{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012407 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012408 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012409 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12410 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012411 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012412 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12413 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012414 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12415 my $PLevel = 0;
12416 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12417 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012418 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012419 return $PLevel if(not $Type{"BaseType"});
12420 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12421 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12422 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012423}
12424
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012425sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012426{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012427 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012428 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012429 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12430 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012431 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012432 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12433 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012434 return %Type if(not $Type{"BaseType"});
12435 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012436 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012437 return %Type;
12438}
12439
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012440sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012441{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012442 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012443 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012444 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12445 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012446 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012447 my $Qual = "";
12448 if($Type{"Type"} eq "Pointer") {
12449 $Qual .= "*";
12450 }
12451 elsif($Type{"Type"} eq "Ref") {
12452 $Qual .= "&";
12453 }
12454 elsif($Type{"Type"} eq "ConstVolatile") {
12455 $Qual .= "const volatile";
12456 }
12457 elsif($Type{"Type"} eq "Const"
12458 or $Type{"Type"} eq "Volatile"
12459 or $Type{"Type"} eq "Restrict") {
12460 $Qual .= lc($Type{"Type"});
12461 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012462 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012463 return $BQual.$Qual;
12464}
12465
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012466sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012467{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012468 my ($TypeId, $Info) = @_;
12469 if(not $TypeId or not $Info
12470 or not $Info->{$TypeId}) {
12471 return ();
12472 }
12473 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012474 return %Type if(not $Type{"BaseType"});
12475 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012476 {
12477 if($Info->{$BTid}) {
12478 return %{$Info->{$BTid}};
12479 }
12480 else { # something is going wrong
12481 return ();
12482 }
12483 }
12484 else {
12485 return %Type;
12486 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012487}
12488
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012489sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012490{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012491 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012492 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012493 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12494 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012495}
12496
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012497sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012498{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012499 my $Symbol = $_[0];
12500 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12501}
12502
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012503sub isInLineInst($$$) {
12504 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12505}
12506
12507sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012508{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012509 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012510 if($CheckObjectsOnly)
12511 {
12512 if($Symbol!~/\A(_Z|\?)/) {
12513 return 0;
12514 }
12515 if(my $Signature = $tr_name{$Symbol})
12516 {
12517 if(index($Signature,">")==-1) {
12518 return 0;
12519 }
12520 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
12521 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012522 if(index($ShortName,"<")!=-1
12523 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012524 return 1;
12525 }
12526 }
12527 }
12528 }
12529 else
12530 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012531 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012532 {
12533 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
12534 {
12535 if(index($ClassName,"<")!=-1) {
12536 return 1;
12537 }
12538 }
12539 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012540 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012541 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012542 if(index($ShortName,"<")!=-1
12543 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012544 return 1;
12545 }
12546 }
12547 }
12548 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012549}
12550
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012551sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012552{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012553 my ($Symbol, $SInfo, $LibVersion) = @_;
12554 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012555 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012556 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012557 { # class specialization
12558 return 1;
12559 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012560 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012561 { # method specialization
12562 return 1;
12563 }
12564 }
12565 return 0;
12566}
12567
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012568sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012569{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012570 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012571 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012572 { # non-public global data
12573 return 0;
12574 }
12575 if($CheckObjectsOnly) {
12576 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
12577 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012578 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012579 { # support for old ABI dumps in --headers-only mode
12580 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12581 {
12582 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12583 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012584 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012585 if(not $PType or $PType eq "Unknown") {
12586 return 0;
12587 }
12588 }
12589 }
12590 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012591 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012592 {
12593 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012594 if($SkipSymbols{$LibVersion}{$Symbol})
12595 { # user defined symbols to ignore
12596 return 0;
12597 }
12598 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12599 if(not $NameSpace and $ClassId)
12600 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012601 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012602 }
12603 if($NameSpace)
12604 { # user defined namespaces to ignore
12605 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12606 return 0;
12607 }
12608 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12609 { # nested namespaces
12610 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12611 return 0;
12612 }
12613 }
12614 }
12615 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
12616 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012617 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012618 { # --skip-headers or <skip_headers> (not <skip_including>)
12619 if($Skip==1) {
12620 return 0;
12621 }
12622 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012623 }
12624 if($SymbolsListPath and not $SymbolsList{$Symbol})
12625 { # user defined symbols
12626 return 0;
12627 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012628 if($SkipSymbolsListPath and $SkipSymbolsList{$Symbol})
12629 { # user defined symbols
12630 return 0;
12631 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012632 if($AppPath and not $SymbolsList_App{$Symbol})
12633 { # user defined symbols (in application)
12634 return 0;
12635 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012636 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12637 { # non-target symbols
12638 return 0;
12639 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012640 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012641 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012642 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012643 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012644 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012645 return 0;
12646 }
12647 }
12648 else
12649 {
12650 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012651 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012652 {
12653 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12654 { # inline virtual methods
12655 if($Type=~/InlineVirt/) {
12656 return 1;
12657 }
12658 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12659 if(not $Allocable)
12660 { # check bases
12661 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12662 {
12663 if(not isCopyingClass($DCId, $LibVersion))
12664 { # exists a derived class without default c-tor
12665 $Allocable=1;
12666 last;
12667 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012669 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012670 if(not $Allocable) {
12671 return 0;
12672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012673 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012674 else
12675 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012676 return 0;
12677 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012678 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012679 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012680 }
12681 }
12682 return 1;
12683}
12684
12685sub mergeImpl()
12686{
12687 my $DiffCmd = get_CmdPath("diff");
12688 if(not $DiffCmd) {
12689 exitStatus("Not_Found", "can't find \"diff\"");
12690 }
12691 foreach my $Interface (sort keys(%{$Symbol_Library{1}}))
12692 { # implementation changes
12693 next if($CompleteSignature{1}{$Interface}{"Private"});
12694 next if(not $CompleteSignature{1}{$Interface}{"Header"} and not $CheckObjectsOnly);
12695 next if(not $Symbol_Library{2}{$Interface} and not $Symbol_Library{2}{$SymVer{2}{$Interface}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012696 if(not symbolFilter($Interface, 1, "Affected", "Binary")) {
12697 next;
12698 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012699 my $Impl1 = canonifyImpl($Interface_Impl{1}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012700 next if(not $Impl1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012701 my $Impl2 = canonifyImpl($Interface_Impl{2}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012702 next if(not $Impl2);
12703 if($Impl1 ne $Impl2)
12704 {
12705 writeFile("$TMP_DIR/impl1", $Impl1);
12706 writeFile("$TMP_DIR/impl2", $Impl2);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012707 my $Diff = `$DiffCmd -rNau \"$TMP_DIR/impl1\" \"$TMP_DIR/impl2\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012708 $Diff=~s/(---|\+\+\+).+\n//g;
12709 $Diff=~s/[ ]{3,}/ /g;
12710 $Diff=~s/\n\@\@/\n \n\@\@/g;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012711 unlink("$TMP_DIR/impl1");
12712 unlink("$TMP_DIR/impl2");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040012713 %{$CompatProblems_Impl{$Interface}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012714 "Diff" => get_CodeView($Diff) );
12715 }
12716 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012717
12718 # clean memory
12719 %Interface_Impl = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012720}
12721
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012722sub canonifyImpl($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012723{
12724 my $FuncBody= $_[0];
12725 return "" if(not $FuncBody);
12726 $FuncBody=~s/0x[a-f\d]+/0x?/g;# addr
12727 $FuncBody=~s/((\A|\n)[a-z]+[\t ]+)[a-f\d]+([^x]|\Z)/$1?$3/g;# call, jump
12728 $FuncBody=~s/# [a-f\d]+ /# ? /g;# call, jump
12729 $FuncBody=~s/%([a-z]+[a-f\d]*)/\%reg/g;# registers
12730 while($FuncBody=~s/\nnop[ \t]*(\n|\Z)/$1/g){};# empty op
12731 $FuncBody=~s/<.+?\.cpp.+?>/<name.cpp>/g;
12732 $FuncBody=~s/(\A|\n)[a-f\d]+ </$1? </g;# 5e74 <_ZN...
12733 $FuncBody=~s/\.L\d+/.L/g;
12734 $FuncBody=~s/#(-?)\d+/#$1?/g;# r3, [r3, #120]
12735 $FuncBody=~s/[\n]{2,}/\n/g;
12736 return $FuncBody;
12737}
12738
12739sub get_CodeView($)
12740{
12741 my $Code = $_[0];
12742 my $View = "";
12743 foreach my $Line (split(/\n/, $Code))
12744 {
12745 if($Line=~s/\A(\+|-)/$1 /g)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012746 { # bold line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012747 $View .= "<tr><td><b>".htmlSpecChars($Line)."</b></td></tr>\n";
12748 }
12749 else {
12750 $View .= "<tr><td>".htmlSpecChars($Line)."</td></tr>\n";
12751 }
12752 }
12753 return "<table class='code_view'>$View</table>\n";
12754}
12755
12756sub getImplementations($$)
12757{
12758 my ($LibVersion, $Path) = @_;
12759 return if(not $LibVersion or not -e $Path);
12760 if($OSgroup eq "macos")
12761 {
12762 my $OtoolCmd = get_CmdPath("otool");
12763 if(not $OtoolCmd) {
12764 exitStatus("Not_Found", "can't find \"otool\"");
12765 }
12766 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012767 foreach my $Line (split(/\n/, `$OtoolCmd -tv \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012768 {
12769 if($Line=~/\A\s*_(\w+)\s*:/i) {
12770 $CurInterface = $1;
12771 }
12772 elsif($Line=~/\A\s*[\da-z]+\s+(.+?)\Z/i) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012773 $Interface_Impl{$LibVersion}{$CurInterface} .= $1."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012774 }
12775 }
12776 }
12777 else
12778 {
12779 my $ObjdumpCmd = get_CmdPath("objdump");
12780 if(not $ObjdumpCmd) {
12781 exitStatus("Not_Found", "can't find \"objdump\"");
12782 }
12783 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012784 foreach my $Line (split(/\n/, `$ObjdumpCmd -d \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012785 {
12786 if($Line=~/\A[\da-z]+\s+<(\w+)>/i) {
12787 $CurInterface = $1;
12788 }
12789 else
12790 { # x86: 51fa:(\t)89 e5 (\t)mov %esp,%ebp
12791 # arm: 5020:(\t)e24cb004(\t)sub(\t)fp, ip, #4(\t); 0x4
12792 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 +040012793 $Interface_Impl{$LibVersion}{$CurInterface} .= $2."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012794 }
12795 }
12796 }
12797 }
12798}
12799
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012800sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012801{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012802 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012803 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12804 {
12805 if(link_symbol($Symbol, 1, "+Deps"))
12806 { # linker can find a new symbol
12807 # in the old-version library
12808 # So, it's not a new symbol
12809 next;
12810 }
12811 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012812 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012813 next;
12814 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012815 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012816 }
12817}
12818
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012819sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012820{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012821 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012822 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12823 {
12824 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012825 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012826 }
12827 if(link_symbol($Symbol, 2, "+Deps"))
12828 { # linker can find an old symbol
12829 # in the new-version library
12830 next;
12831 }
12832 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012833 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012834 next;
12835 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012836 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012837 }
12838}
12839
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012840sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012841{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012842 my $Level = $_[0];
12843 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012844 { # checking added symbols
12845 next if($CompleteSignature{2}{$Symbol}{"Private"});
12846 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012847 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012848 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012849 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012850 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012851 { # checking removed symbols
12852 next if($CompleteSignature{1}{$Symbol}{"Private"});
12853 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012854 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012855 { # skip v-tables for templates, that should not be imported by applications
12856 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012857 if(my $CName = $VTableClass{$Symbol})
12858 {
12859 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12860 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012861 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012862 next;
12863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012864 }
12865 }
12866 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012867 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012868 }
12869 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12870 { # symbols for pure virtual methods cannot be called by clients
12871 next;
12872 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012873 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012874 }
12875}
12876
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012877sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012878{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012879 my ($LibVersion, $V) = @_;
12880 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12881 return $Cache{"checkDump"}{$LibVersion}{$V};
12882 }
12883 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012884}
12885
12886sub detectAdded_H($)
12887{
12888 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012889 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12890 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012891 if($Level eq "Source")
12892 { # remove symbol version
12893 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12894 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012895
12896 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12897 { # skip artificial constructors
12898 next;
12899 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012900 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012901 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12902 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012903 next;
12904 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012905 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012906 next;
12907 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012908 if(not defined $CompleteSignature{1}{$Symbol}
12909 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12910 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012911 if($UsedDump{2}{"SrcBin"})
12912 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012913 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012914 { # support for old and different (!) ABI dumps
12915 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12916 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012917 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012918 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012919 {
12920 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12921 {
12922 if($Lang eq "C")
12923 { # support for old ABI dumps: missed extern "C" functions
12924 next;
12925 }
12926 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012927 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012928 else
12929 {
12930 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012931 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012932 next;
12933 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012934 }
12935 }
12936 }
12937 }
12938 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012939 }
12940 }
12941}
12942
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012943sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012944{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012945 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012946 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12947 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012948 if($Level eq "Source")
12949 { # remove symbol version
12950 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12951 $Symbol=$SN;
12952 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012953 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12954 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012955 next;
12956 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012957 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012958 next;
12959 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012960 if(not defined $CompleteSignature{2}{$Symbol}
12961 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012962 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012963 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012964 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012965 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012966 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012967 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12968 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012969 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012970 if($CheckHeadersOnly)
12971 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012972 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12973 {
12974 if($Lang eq "C")
12975 { # support for old ABI dumps: missed extern "C" functions
12976 next;
12977 }
12978 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012979 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012980 else
12981 {
12982 if(not link_symbol($Symbol, 1, "-Deps"))
12983 { # skip removed inline symbols
12984 next;
12985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012986 }
12987 }
12988 }
12989 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012990 if(not checkDump(1, "2.15"))
12991 {
12992 if($Symbol=~/_IT_E\Z/)
12993 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12994 next;
12995 }
12996 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012997 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12998 {
12999 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
13000 {
13001 if(defined $Constants{2}{$Short})
13002 {
13003 my $Val = $Constants{2}{$Short}{"Value"};
13004 if(defined $Func_ShortName{2}{$Val})
13005 { # old name defined to new
13006 next;
13007 }
13008 }
13009 }
13010
13011 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013012 $RemovedInt{$Level}{$Symbol} = 1;
13013 if($Level eq "Source")
13014 { # search for a source-compatible equivalent
13015 setAlternative($Symbol, $Level);
13016 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013017 }
13018 }
13019}
13020
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013021sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013022{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013023 my $Level = $_[0];
13024 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013025 { # checking added symbols
13026 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013027 next if($CompleteSignature{2}{$Symbol}{"Private"});
13028 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013029 if($Level eq "Binary")
13030 {
13031 if($CompleteSignature{2}{$Symbol}{"InLine"})
13032 {
13033 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
13034 { # skip inline non-virtual functions
13035 next;
13036 }
13037 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013038 }
13039 else
13040 { # Source
13041 if($SourceAlternative_B{$Symbol}) {
13042 next;
13043 }
13044 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013045 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013046 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013047 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013048 { # checking removed symbols
13049 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013050 next if($CompleteSignature{1}{$Symbol}{"Private"});
13051 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013052 if($Level eq "Binary")
13053 {
13054 if($CompleteSignature{1}{$Symbol}{"InLine"})
13055 {
13056 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13057 { # skip inline non-virtual functions
13058 next;
13059 }
13060 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013061 }
13062 else
13063 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013064 if(my $Alt = $SourceAlternative{$Symbol})
13065 {
13066 if(defined $CompleteSignature{1}{$Alt}
13067 and $CompleteSignature{1}{$Symbol}{"Const"})
13068 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013069 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013070 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013071 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013072 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013073 }
13074 else
13075 { # do NOT show removed symbol
13076 next;
13077 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013078 }
13079 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013080 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013081 }
13082}
13083
13084sub addParamNames($)
13085{
13086 my $LibraryVersion = $_[0];
13087 return if(not keys(%AddIntParams));
13088 my $SecondVersion = $LibraryVersion==1?2:1;
13089 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13090 {
13091 next if(not keys(%{$AddIntParams{$Interface}}));
13092 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013093 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013094 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13095 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013096 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013097 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13098 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13099 {
13100 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13101 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13102 }
13103 }
13104 else {
13105 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13106 }
13107 }
13108 }
13109 }
13110}
13111
13112sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013113{ # detect changed typedefs to show
13114 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013115 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13116 {
13117 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013118 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13119 if(not $BName1 or isAnon($BName1)) {
13120 next;
13121 }
13122 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13123 if(not $BName2 or isAnon($BName2)) {
13124 next;
13125 }
13126 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013127 $ChangedTypedef{$Typedef} = 1;
13128 }
13129 }
13130}
13131
13132sub get_symbol_suffix($$)
13133{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013134 my ($Symbol, $Full) = @_;
13135 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013136 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013137 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013138 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013139 if(not $Full) {
13140 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13141 }
13142 return $Suffix;
13143}
13144
13145sub get_symbol_prefix($$)
13146{
13147 my ($Symbol, $LibVersion) = @_;
13148 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13149 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13150 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013151 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013152 }
13153 return $ShortName;
13154}
13155
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013156sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013157{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013158 my $Symbol = $_[0];
13159 my $PSymbol = $Symbol;
13160 if(not defined $CompleteSignature{2}{$PSymbol}
13161 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13162 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13163 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013164 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013165 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013166 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013167 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013168 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13169 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013170 {
13171 if(defined $CompleteSignature{2}{$PSymbol}
13172 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13173 {
13174 $SourceAlternative{$Symbol} = $PSymbol;
13175 $SourceAlternative_B{$PSymbol} = $Symbol;
13176 if(not defined $CompleteSignature{1}{$PSymbol}
13177 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13178 $SourceReplacement{$Symbol} = $PSymbol;
13179 }
13180 }
13181 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013182 }
13183 else
13184 {
13185 foreach my $Sp ("KV", "VK", "K", "V")
13186 {
13187 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13188 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13189 {
13190 if(defined $CompleteSignature{2}{$PSymbol}
13191 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13192 {
13193 $SourceAlternative{$Symbol} = $PSymbol;
13194 $SourceAlternative_B{$PSymbol} = $Symbol;
13195 if(not defined $CompleteSignature{1}{$PSymbol}
13196 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13197 $SourceReplacement{$Symbol} = $PSymbol;
13198 }
13199 }
13200 }
13201 $PSymbol = $Symbol;
13202 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013203 }
13204 }
13205 }
13206 return "";
13207}
13208
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013209sub getSymKind($$)
13210{
13211 my ($Symbol, $LibVersion) = @_;
13212 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13213 {
13214 return "Global_Data";
13215 }
13216 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13217 {
13218 return "Method";
13219 }
13220 return "Function";
13221}
13222
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013223sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013224{
13225 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013226 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013227
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013228 mergeBases($Level);
13229
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013230 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013231 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013232 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013233 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013234 next;
13235 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013236 if(defined $CompleteSignature{1}{$Symbol}
13237 and $CompleteSignature{1}{$Symbol}{"Header"})
13238 { # double-check added symbol
13239 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013240 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013241 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013242 next;
13243 }
13244 if($Symbol=~/\A(_Z|\?)/)
13245 { # C++
13246 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13247 }
13248 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13249 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013250 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13251 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013252 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013253 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013254 {
13255 if($TName_Tid{1}{$AffectedClass_Name})
13256 { # class should exist in previous version
13257 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13258 { # old v-table is NOT copied by old applications
13259 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13260 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013261 "Target"=>get_Signature($Symbol, 2),
13262 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013263 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013264 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013265 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013266 }
13267 }
13268 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013269 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13270 { # check all removed exported symbols
13271 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013272 next;
13273 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013274 if(defined $CompleteSignature{2}{$Symbol}
13275 and $CompleteSignature{2}{$Symbol}{"Header"})
13276 { # double-check removed symbol
13277 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013278 }
13279 if($CompleteSignature{1}{$Symbol}{"Private"})
13280 { # skip private methods
13281 next;
13282 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013283 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013284 next;
13285 }
13286 $CheckedSymbols{$Level}{$Symbol} = 1;
13287 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13288 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013289 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13290 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013291 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013292 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13293 {
13294 if($TName_Tid{2}{$AffectedClass_Name})
13295 { # class should exist in newer version
13296 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13297 { # old v-table is NOT copied by old applications
13298 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13299 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013300 "Target"=>get_Signature($OverriddenMethod, 1),
13301 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013302 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013303 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013305 }
13306 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013307 if($Level eq "Binary"
13308 and $OSgroup eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013309 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013310 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013311 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013312 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013313 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013314 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013315 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013316 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013317 {
13318 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13319 "Target"=>$tr_name{$Symbol},
13320 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013321 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013322 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013323 else
13324 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013325 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013326 "Target"=>$tr_name{$Symbol},
13327 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013328 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013329 }
13330 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013331 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013332 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013333 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013334 {
13335 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13336 "Target"=>$tr_name{$Symbol},
13337 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013338 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013339 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013340 else
13341 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013342 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013343 "Target"=>$tr_name{$Symbol},
13344 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013345 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013346 }
13347 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013348 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13349 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13350 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13351 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13352 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013353 {
13354 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013355 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013356 $ProblemType = "Global_Data_Symbol_Changed_Type";
13357 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013358 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13359 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013360 "Old_Type"=>$RTName1,
13361 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013362 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013363 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013364 }
13365 }
13366 }
13367 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013368 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013369 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013370 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013371 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013372 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013373 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013374 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013375 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13376 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013377 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013378 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013379 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013380 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013381 }
13382 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013383 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13384 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013385 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013386 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013387 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013388 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013389 }
13390 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013391 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013392 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013393 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013394 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013395 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013396 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013397 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013398 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013399 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013400 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013401 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013402 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013403 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013404 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013405 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013406 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013407 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013408 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013409 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013410 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013411 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013412 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013413 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013414 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013415 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013416 { # "volatile" to non-"volatile"
13417
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013418 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013419 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013420 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013421 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013422 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013423 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013424 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013425 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013426 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013427 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013428 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013429 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013430 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013431 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013432 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013433 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013434 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013435 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13436 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013437 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013438 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013439 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013440 }
13441 }
13442 }
13443 }
13444 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013445 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13446 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013447 $CurrentSymbol = $Symbol;
13448
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013449 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13450 if($Level eq "Source")
13451 { # remove symbol version
13452 $Symbol=$SN;
13453 }
13454 else
13455 { # Binary
13456 if(not $SV)
13457 { # symbol without version
13458 if(my $VSym = $SymVer{1}{$Symbol})
13459 { # the symbol is linked with versioned symbol
13460 if($CompleteSignature{2}{$VSym}{"MnglName"})
13461 { # show report for symbol@ver only
13462 next;
13463 }
13464 elsif(not link_symbol($VSym, 2, "-Deps"))
13465 { # changed version: sym@v1 to sym@v2
13466 # do NOT show report for symbol
13467 next;
13468 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013469 }
13470 }
13471 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013472 my $PSymbol = $Symbol;
13473 if($Level eq "Source"
13474 and my $S = $SourceReplacement{$Symbol})
13475 { # take a source-compatible replacement function
13476 $PSymbol = $S;
13477 }
13478 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013479 { # private symbols
13480 next;
13481 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013482 if(not defined $CompleteSignature{1}{$Symbol}
13483 or not defined $CompleteSignature{2}{$PSymbol})
13484 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013485 next;
13486 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013487 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13488 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13489 { # no mangled name
13490 next;
13491 }
13492 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13493 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013494 { # without a header
13495 next;
13496 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013497
13498 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13499 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13500 { # became pure
13501 next;
13502 }
13503 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13504 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13505 { # became non-pure
13506 next;
13507 }
13508
13509 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13510 { # exported, target, inline virtual and pure virtual
13511 next;
13512 }
13513 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13514 { # exported, target, inline virtual and pure virtual
13515 next;
13516 }
13517
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013518 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013519 {
13520 if($CompleteSignature{1}{$Symbol}{"Data"}
13521 and $CompleteSignature{2}{$PSymbol}{"Data"})
13522 {
13523 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13524 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13525 if(defined $Value1)
13526 {
13527 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13528 if(defined $Value2)
13529 {
13530 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13531 if($Value1 ne $Value2)
13532 {
13533 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13534 "Old_Value"=>$Value1,
13535 "New_Value"=>$Value2,
13536 "Target"=>get_Signature($Symbol, 1) );
13537 }
13538 }
13539 }
13540 }
13541 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013542
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013543 if($CompleteSignature{2}{$PSymbol}{"Private"})
13544 {
13545 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13546 "Target"=>get_Signature_M($PSymbol, 2) );
13547 }
13548 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13549 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13550 {
13551 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13552 "Target"=>get_Signature_M($PSymbol, 2) );
13553 }
13554 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13555 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13556 {
13557 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13558 "Target"=>get_Signature_M($PSymbol, 2) );
13559 }
13560
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013561 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013562 mergeVirtualTables($Symbol, $Level);
13563
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013564 if($COMPILE_ERRORS)
13565 { # if some errors occurred at the compiling stage
13566 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013567 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013568 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013569 { # missed information about parameters in newer version
13570 next;
13571 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013572 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013573 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013574 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013575 next;
13576 }
13577 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013578 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013579 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013580 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013581 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13582 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013583 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13584 "Target"=>get_Signature($Symbol, 1)
13585 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013586 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013587 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013588 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13589 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013590 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013591 "Target"=>get_Signature($Symbol, 1)
13592 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013593 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013594 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13595 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013596 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013597 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013598 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013599 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13600 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13601 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013602 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013603 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013604 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13605 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013606 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013607 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013608 my $ProblemType = "Virtual_Method_Position";
13609 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13610 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013611 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013612 if(isUsedClass($Class_Id, 1, $Level))
13613 {
13614 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013615 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013616 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013617 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13618 next;
13619 }
13620 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013621 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013622 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13623 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013624 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013625 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013626 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013627 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013628 }
13629 }
13630 }
13631 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013632 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13633 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013634 { # do NOT check type changes in pure virtuals
13635 next;
13636 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013637 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013638 if($Symbol=~/\A(_Z|\?)/
13639 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013640 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013641 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013642 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013643 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013644 }
13645 }
13646 else
13647 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013648 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013649 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013650 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013651 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13652 last if($PType2_Name eq "...");
13653 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13654 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013655 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013656 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013657 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013658 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13659 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013660 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13661 $ParamPos_Prev = "lost";
13662 }
13663 }
13664 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013665 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013666 }
13667 if($ParamPos_Prev eq "lost")
13668 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013669 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013670 {
13671 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013672 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013673 $ProblemType = "Added_Unnamed_Parameter";
13674 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013675 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013676 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013677 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013678 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013679 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013680 }
13681 else
13682 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013683 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013684 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013685 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013686 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13687 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013688 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013689 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013690 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013691 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013692 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013693 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013694 "Param_Type"=>$PType2_Name,
13695 "Old_Value"=>$PName_Old,
13696 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013697 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013698 }
13699 }
13700 else
13701 {
13702 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013703 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013704 $ProblemType = "Added_Middle_Unnamed_Parameter";
13705 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013706 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013707 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013708 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013709 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013710 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013711 }
13712 }
13713 }
13714 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013715 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013716 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013717 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013718 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013719 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013720 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013721 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013722 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013723 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013724 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13725 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013726 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013727 }
13728 }
13729 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013730 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013731 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013732 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013733 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13734 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013735 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13736 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013737 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013738 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013739 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013740 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13741 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013742 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13743 $ParamPos_New = "lost";
13744 }
13745 }
13746 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013747 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013748 }
13749 if($ParamPos_New eq "lost")
13750 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013751 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013752 {
13753 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013754 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013755 $ProblemType = "Removed_Unnamed_Parameter";
13756 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013757 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013758 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013759 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013760 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013761 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013762 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013763 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013764 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013765 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013766 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013767 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013768 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013769 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013770 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013771 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013772 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013773 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013774 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013775 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013776 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013777 "Old_Value"=>$PName,
13778 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013779 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013780 }
13781 }
13782 else
13783 {
13784 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013785 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013786 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13787 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013788 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013789 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013790 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013791 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013792 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013793 }
13794 }
13795 }
13796 }
13797 }
13798 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013799 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13800 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013801 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013802
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013803 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013804 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013805 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13806 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013807 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013808
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013809 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013810 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013811 if($SubProblemType eq "Return_Type_And_Size") {
13812 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13813 }
13814 elsif($SubProblemType eq "Return_Type_Format") {
13815 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13816 }
13817 else {
13818 $ProblemTypes{"Global_Data_Type"} = 1;
13819 }
13820
13821 # quals
13822 if($SubProblemType eq "Return_Type"
13823 or $SubProblemType eq "Return_Type_And_Size"
13824 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013825 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013826 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13827 { # const to non-const
13828 if($RR==2) {
13829 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13830 }
13831 else {
13832 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13833 }
13834 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013835 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013836 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13837 { # non-const to const
13838 if($RA==2) {
13839 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13840 }
13841 else {
13842 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13843 }
13844 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013845 }
13846 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013847 }
13848 else
13849 {
13850 # quals
13851 if($SubProblemType eq "Return_Type"
13852 or $SubProblemType eq "Return_Type_And_Size"
13853 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013854 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013855 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013856 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013857 if(addedQual($Old_Value, $New_Value, "volatile"))
13858 {
13859 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13860 if($Level ne "Source"
13861 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13862 $ProblemTypes{"Return_Type"} = 1;
13863 }
13864 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013865 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013866 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13867 {
13868 if($RA==2) {
13869 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13870 }
13871 else {
13872 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13873 }
13874 if($Level ne "Source"
13875 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13876 $ProblemTypes{"Return_Type"} = 1;
13877 }
13878 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013879 }
13880 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013881 if($Level eq "Binary"
13882 and not $CompleteSignature{1}{$Symbol}{"Data"})
13883 {
13884 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13885 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13886 { # if one of the architectures is unknown
13887 # then set other arhitecture to unknown too
13888 ($Arch1, $Arch2) = ("unknown", "unknown");
13889 }
13890 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013891 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013892 {
13893 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13894 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13895 }
13896 else
13897 {
13898 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13899 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13900 }
13901
13902 if($SubProblemType eq "Return_Type_Became_Void")
13903 {
13904 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13905 { # parameters stack has been affected
13906 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013907 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013908 }
13909 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013910 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013911 }
13912 }
13913 }
13914 elsif($SubProblemType eq "Return_Type_From_Void")
13915 {
13916 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13917 { # parameters stack has been affected
13918 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013919 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013920 }
13921 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013922 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013923 }
13924 }
13925 }
13926 elsif($SubProblemType eq "Return_Type"
13927 or $SubProblemType eq "Return_Type_And_Size"
13928 or $SubProblemType eq "Return_Type_Format")
13929 {
13930 if($Conv1{"Method"} ne $Conv2{"Method"})
13931 {
13932 if($Conv1{"Method"} eq "stack")
13933 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013934 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013935 }
13936 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013937 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013938 }
13939 }
13940 else
13941 {
13942 if($Conv1{"Method"} eq "reg")
13943 {
13944 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13945 {
13946 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013947 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013948 }
13949 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013950 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013951 }
13952 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013953 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013954 }
13955 }
13956 }
13957 }
13958 }
13959 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013960
13961 if(not keys(%ProblemTypes))
13962 { # default
13963 $ProblemTypes{$SubProblemType} = 1;
13964 }
13965
13966 foreach my $ProblemType (keys(%ProblemTypes))
13967 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013968 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013969 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013970 }
13971 if($ReturnType1_Id and $ReturnType2_Id)
13972 {
13973 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013974 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13975
13976 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013977
13978 if($CompleteSignature{1}{$Symbol}{"Data"})
13979 {
13980 if($Level eq "Binary")
13981 {
13982 if(get_PLevel($ReturnType1_Id, 1)==0)
13983 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013984 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013985 { # add "Global_Data_Size" problem
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013986 my $New_Value = $Sub_SubProblems->{$SubProblemType}{"New_Value"};
13987 my $Old_Value = $Sub_SubProblems->{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013988 if($SubProblemType eq "DataType_Size")
13989 { # add a new problem
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013990 $AddProblems->{"Global_Data_Size"} = $Sub_SubProblems->{$SubProblemType};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013991 }
13992 }
13993 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013994 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013995 {
13996 if(defined $GlobalDataObject{1}{$Symbol}
13997 and defined $GlobalDataObject{2}{$Symbol})
13998 {
13999 my $Old_Size = $GlobalDataObject{1}{$Symbol};
14000 my $New_Size = $GlobalDataObject{2}{$Symbol};
14001 if($Old_Size!=$New_Size)
14002 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014003 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014004 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014005 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014006 }
14007 }
14008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014009 }
14010 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014011
14012 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014013 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014014 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014015 {
14016 my $NewLocation = ($SubLocation)?"retval->".$SubLocation:"retval";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014017 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
14018 }
14019 }
14020
14021 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
14022 {
14023 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
14024 {
14025 my $NewLocation = ($SubLocation)?"retval->".$SubLocation:"retval";
14026 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014027 }
14028 }
14029 }
14030
14031 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014032 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
14033 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
14034 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014035 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014036 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014037 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
14038 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014039 if($ThisPtr1_Id and $ThisPtr2_Id)
14040 {
14041 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014042 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14043 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014044 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014045 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014046 {
14047 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014048 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014049 }
14050 }
14051 }
14052 }
14053 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014054 if($Level eq "Binary") {
14055 mergeVTables($Level);
14056 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014057 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14058 $CheckedSymbols{$Level}{$Symbol} = 1;
14059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014060}
14061
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014062sub rmQuals($$)
14063{
14064 my ($Value, $Qual) = @_;
14065 if(not $Qual) {
14066 return $Value;
14067 }
14068 if($Qual eq "all")
14069 { # all quals
14070 $Qual = "const|volatile|restrict";
14071 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014072 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014073 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014074 }
14075 return $Value;
14076}
14077
14078sub cmpBTypes($$$$)
14079{
14080 my ($T1, $T2, $V1, $V2) = @_;
14081 $T1 = uncover_typedefs($T1, $V1);
14082 $T2 = uncover_typedefs($T2, $V2);
14083 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14084}
14085
14086sub addedQual($$$)
14087{
14088 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014089 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014090}
14091
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014092sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014093{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014094 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014095 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014096}
14097
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014098sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014099{
14100 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14101 $Old_Value = uncover_typedefs($Old_Value, $V1);
14102 $New_Value = uncover_typedefs($New_Value, $V2);
14103 if($Old_Value eq $New_Value)
14104 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014105 return 0;
14106 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014107 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014108 { # without a qual
14109 return 0;
14110 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014111 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014112 { # became non-qual
14113 return 1;
14114 }
14115 else
14116 {
14117 my @BQ1 = getQualModel($Old_Value, $Qual);
14118 my @BQ2 = getQualModel($New_Value, $Qual);
14119 foreach (0 .. $#BQ1)
14120 { # removed qual
14121 if($BQ1[$_]==1
14122 and $BQ2[$_]!=1)
14123 {
14124 return 2;
14125 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014126 }
14127 }
14128 return 0;
14129}
14130
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014131sub getQualModel($$)
14132{
14133 my ($Value, $Qual) = @_;
14134 if(not $Qual) {
14135 return $Value;
14136 }
14137
14138 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014139 while($Value=~/(\w+)/ and $1 ne $Qual) {
14140 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014141 }
14142 $Value=~s/[^\*\&\w]+//g;
14143
14144 # modeling
14145 # int*const*const == 011
14146 # int**const == 001
14147 my @Model = ();
14148 my @Elems = split(/[\*\&]/, $Value);
14149 if(not @Elems) {
14150 return (0);
14151 }
14152 foreach (@Elems)
14153 {
14154 if($_ eq $Qual) {
14155 push(@Model, 1);
14156 }
14157 else {
14158 push(@Model, 0);
14159 }
14160 }
14161
14162 return @Model;
14163}
14164
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014165my %StringTypes = map {$_=>1} (
14166 "char*",
14167 "char const*"
14168);
14169
14170my %CharTypes = map {$_=>1} (
14171 "char",
14172 "char const"
14173);
14174
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014175sub showVal($$$)
14176{
14177 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014178 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014179 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014180 if(substr($Value, 0, 2) eq "_Z")
14181 {
14182 if(my $Unmangled = $tr_name{$Value}) {
14183 return $Unmangled;
14184 }
14185 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014186 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014187 { # strings
14188 return "\"$Value\"";
14189 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014190 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014191 { # characters
14192 return "\'$Value\'";
14193 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014194 if($Value eq "")
14195 { # other
14196 return "\'\'";
14197 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014198 return $Value;
14199}
14200
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014201sub getRegs($$$)
14202{
14203 my ($LibVersion, $Symbol, $Pos) = @_;
14204
14205 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14206 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014207 my %Regs = ();
14208 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14209 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014210 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014211 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14212 }
14213 }
14214
14215 return join(", ", sort keys(%Regs));
14216 }
14217
14218 return undef;
14219}
14220
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014221sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014222{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014223 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014224 if(not $Symbol) {
14225 return;
14226 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014227 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14228 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14229 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14230 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014231 if(not $PType1_Id
14232 or not $PType2_Id) {
14233 return;
14234 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014235
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014236 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014237 { # do not merge "this"
14238 if($PName1 eq "this" or $PName2 eq "this") {
14239 return;
14240 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014241 }
14242
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014243 my %Type1 = get_Type($PType1_Id, 1);
14244 my %Type2 = get_Type($PType2_Id, 2);
14245 my %BaseType1 = get_BaseType($PType1_Id, 1);
14246 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014247 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014248
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014249 if($Level eq "Binary")
14250 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014251 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014252 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14253 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14254 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14255 {
14256 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014257 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014258 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014259 }
14260 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14261 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14262 {
14263 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014264 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014265 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014266 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014267 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014268
14269 if(defined $UsedDump{1}{"DWARF"}
14270 and defined $UsedDump{2}{"DWARF"})
14271 {
14272 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14273 {
14274 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14275 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14276 if($Old_Regs and $New_Regs)
14277 {
14278 if($Old_Regs ne $New_Regs)
14279 {
14280 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14281 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014282 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014283 "Old_Value"=>$Old_Regs,
14284 "New_Value"=>$New_Regs );
14285 }
14286 }
14287 elsif($Old_Regs and not $New_Regs)
14288 {
14289 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14290 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014291 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014292 "Old_Value"=>$Old_Regs );
14293 }
14294 elsif(not $Old_Regs and $New_Regs)
14295 {
14296 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14297 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014298 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014299 "New_Value"=>$New_Regs );
14300 }
14301 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14302 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14303 {
14304 if($Old_Offset ne $New_Offset)
14305 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014306 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14307 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14308
14309 $Old_Offset = $Old_Offset - $Start1;
14310 $New_Offset = $New_Offset - $Start2;
14311
14312 if($Old_Offset ne $New_Offset)
14313 {
14314 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14315 "Target"=>$PName1,
14316 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14317 "Old_Value"=>$Old_Offset,
14318 "New_Value"=>$New_Offset );
14319 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014320 }
14321 }
14322 }
14323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014324 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014325 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14326 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014327 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014328 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014329 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14330 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014331 if(not checkDump(1, "2.13")
14332 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014333 { # support for old ABI dumps
14334 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014335 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014336 if($Type1{"Name"} eq "bool"
14337 and $Value_Old eq "false" and $Value_New eq "0")
14338 { # int class::method ( bool p = 0 );
14339 # old ABI dumps: "false"
14340 # new ABI dumps: "0"
14341 $Value_Old = "0";
14342 }
14343 }
14344 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014345 if(not checkDump(1, "2.18")
14346 and checkDump(2, "2.18"))
14347 { # support for old ABI dumps
14348 if(not defined $Value_Old
14349 and substr($Value_New, 0, 2) eq "_Z") {
14350 $Value_Old = $Value_New;
14351 }
14352 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014353 if(defined $Value_Old)
14354 {
14355 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14356 if(defined $Value_New)
14357 {
14358 $Value_New = showVal($Value_New, $PType2_Id, 2);
14359 if($Value_Old ne $Value_New)
14360 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014361 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014362 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014363 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014364 "Old_Value"=>$Value_Old,
14365 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014366 }
14367 }
14368 else
14369 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014370 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014371 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014372 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014373 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014374 }
14375 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014376 elsif(defined $Value_New)
14377 {
14378 $Value_New = showVal($Value_New, $PType2_Id, 2);
14379 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14380 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014381 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014382 "New_Value"=>$Value_New );
14383 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014384 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014385
14386 if($ChkRnmd)
14387 {
14388 if($PName1 and $PName2 and $PName1 ne $PName2
14389 and $PType1_Id!=-1 and $PType2_Id!=-1
14390 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14391 { # except unnamed "..." value list (Id=-1)
14392 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14393 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014394 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014395 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14396 "Old_Value"=>$PName1,
14397 "New_Value"=>$PName2,
14398 "New_Signature"=>get_Signature($Symbol, 2) );
14399 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014400 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014401
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014402 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014403 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014404
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014405 foreach my $SubProblemType (keys(%SubProblems))
14406 { # add new problems, remove false alarms
14407 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14408 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014409
14410 # quals
14411 if($SubProblemType eq "Parameter_Type"
14412 or $SubProblemType eq "Parameter_Type_And_Size"
14413 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014414 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014415 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014416 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014417 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014418 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014419 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014420 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14421 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14422 }
14423 }
14424 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14425 {
14426 if(removedQual($Old_Value, $New_Value, "volatile")) {
14427 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014428 }
14429 }
14430 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14431 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14432 { # int to "int const"
14433 delete($SubProblems{$SubProblemType});
14434 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014435 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014436 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14437 { # "int const" to int
14438 delete($SubProblems{$SubProblemType});
14439 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014440 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14441 { # "const" to non-"const"
14442 if($RR==2) {
14443 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14444 }
14445 else {
14446 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14447 }
14448 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014449 }
14450 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014451
14452 if($Level eq "Source")
14453 {
14454 foreach my $SubProblemType (keys(%SubProblems))
14455 {
14456 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14457 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14458
14459 if($SubProblemType eq "Parameter_Type")
14460 {
14461 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14462 delete($SubProblems{$SubProblemType});
14463 }
14464 }
14465 }
14466 }
14467
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014468 foreach my $SubProblemType (keys(%SubProblems))
14469 { # modify/register problems
14470 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14471 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014472 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14473 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014474
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014475 my $NewProblemType = $SubProblemType;
14476 if($Old_Value eq "..." and $New_Value ne "...")
14477 { # change from "..." to "int"
14478 if($ParamPos1==0)
14479 { # ISO C requires a named argument before "..."
14480 next;
14481 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014482 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014483 }
14484 elsif($New_Value eq "..." and $Old_Value ne "...")
14485 { # change from "int" to "..."
14486 if($ParamPos2==0)
14487 { # ISO C requires a named argument before "..."
14488 next;
14489 }
14490 $NewProblemType = "Parameter_Became_VaList";
14491 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014492 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014493 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014494 {
14495 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014496 if($Arch1 eq "unknown"
14497 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014498 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014499 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014500 ($Arch1, $Arch2) = ("unknown", "unknown");
14501 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014502 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014503 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014504 { # real
14505 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14506 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14507 }
14508 else
14509 { # model
14510 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14511 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14512 }
14513 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014514 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014515 if($Conv1{"Method"} eq "stack")
14516 {
14517 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14518 $NewProblemType = "Parameter_Type_And_Stack";
14519 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014520 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014521 elsif($Conv1{"Method"} eq "reg")
14522 {
14523 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14524 $NewProblemType = "Parameter_Type_And_Register";
14525 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014526 }
14527 }
14528 else
14529 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014530 if($Conv1{"Method"} eq "stack") {
14531 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014532 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014533 elsif($Conv1{"Method"} eq "register") {
14534 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014535 }
14536 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014537 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14538 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014539 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014540 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014541 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014542 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014543 "New_Signature"=>get_Signature($Symbol, 2) );
14544 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014545 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014546
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014547 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014548
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014549 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014550 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14551 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014552 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014553 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014554 {
14555 my $NewProblemType = $SubProblemType;
14556 if($SubProblemType eq "DataType_Size")
14557 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014558 if($Type1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014559 { # stack has been affected
14560 $NewProblemType = "DataType_Size_And_Stack";
14561 }
14562 }
14563 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014564 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014565 }
14566 }
14567}
14568
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014569sub find_ParamPair_Pos_byName($$$)
14570{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014571 my ($Name, $Symbol, $LibVersion) = @_;
14572 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014573 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014574 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14575 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014576 {
14577 return $ParamPos;
14578 }
14579 }
14580 return "lost";
14581}
14582
14583sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14584{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014585 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014586 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014587 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014588 {
14589 next if($Order eq "backward" and $ParamPos>$MediumPos);
14590 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014591 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14592 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014593 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014594 push(@Positions, $ParamPos);
14595 }
14596 }
14597 return @Positions;
14598}
14599
14600sub getTypeIdByName($$)
14601{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014602 my ($TypeName, $LibVersion) = @_;
14603 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014604}
14605
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014606sub diffTypes($$$)
14607{
14608 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14609 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14610 }
14611 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14612 { # skip recursive declarations
14613 return 0;
14614 }
14615
14616 pushType($_[0], $_[1], \@RecurTypes_Diff);
14617 my $Diff = diffTypes_I(@_);
14618 pop(@RecurTypes_Diff);
14619
14620 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14621}
14622
14623sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014624{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014625 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014626
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014627 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14628 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014629
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014630 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14631 { # equal types
14632 return 0;
14633 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014634 if($Type1_Pure{"Name"} eq "void")
14635 { # from void* to something
14636 return 0;
14637 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014638 if($Type1_Pure{"Name"}=~/\*/
14639 or $Type2_Pure{"Name"}=~/\*/)
14640 { # compared in detectTypeChange()
14641 return 0;
14642 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014643
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014644 my %FloatType = map {$_=>1} (
14645 "float",
14646 "double",
14647 "long double"
14648 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014649
14650 my $T1 = $Type1_Pure{"Type"};
14651 my $T2 = $Type2_Pure{"Type"};
14652
14653 if($T1 eq "Struct"
14654 and $T2 eq "Class")
14655 { # compare as data structures
14656 $T2 = "Struct";
14657 }
14658
14659 if($T1 eq "Class"
14660 and $T2 eq "Struct")
14661 { # compare as data structures
14662 $T1 = "Struct";
14663 }
14664
14665 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014666 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014667 if($T1 eq "Intrinsic"
14668 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014669 { # "int" to "enum"
14670 return 0;
14671 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014672 elsif($T2 eq "Intrinsic"
14673 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014674 { # "enum" to "int"
14675 return 0;
14676 }
14677 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014678 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014679 # ...
14680 return 1;
14681 }
14682 }
14683 else
14684 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014685 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014686 {
14687 if($FloatType{$Type1_Pure{"Name"}}
14688 or $FloatType{$Type2_Pure{"Name"}})
14689 { # "float" to "double"
14690 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014691 if($Level eq "Source")
14692 { # Safe
14693 return 0;
14694 }
14695 else {
14696 return 1;
14697 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014698 }
14699 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014700 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014701 {
14702 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14703 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014704 if(not @Membs1
14705 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014706 { # private
14707 return 0;
14708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014709 if($#Membs1!=$#Membs2)
14710 { # different number of elements
14711 return 1;
14712 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014713 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014714 {
14715 foreach my $Pos (@Membs1)
14716 { # compare elements by name and value
14717 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14718 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14719 { # different names
14720 return 1;
14721 }
14722 }
14723 }
14724 else
14725 {
14726 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014727 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014728 if($Level eq "Source")
14729 {
14730 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14731 { # different names
14732 return 1;
14733 }
14734 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014735
14736 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14737 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14738
14739 if($MT1{"Name"} ne $MT2{"Name"}
14740 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14741 {
14742 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14743 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14744
14745 if($PL1 ne $PL2)
14746 { # different pointer level
14747 return 1;
14748 }
14749
14750 # compare base types
14751 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14752 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14753
14754 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14755 { # different types
14756 return 1;
14757 }
14758 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014759 }
14760 }
14761 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014762 else
14763 {
14764 # TODO: arrays, etc.
14765 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014766 }
14767 return 0;
14768}
14769
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014770sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014771{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014772 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014773 if(not $Type1_Id or not $Type2_Id) {
14774 return ();
14775 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014776 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014777 my %Type1 = get_Type($Type1_Id, 1);
14778 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014779 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14780 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14781 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14782 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 +040014783
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014784 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14785 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014786 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14787 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14788 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14789 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14790 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14791 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14792 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014793 if($Type1{"Name"} eq $Type2{"Name"})
14794 {
14795 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14796 { # will be reported in mergeTypes() as typedef problem
14797 return ();
14798 }
14799 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14800 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14801 if(%Typedef_1 and %Typedef_2)
14802 {
14803 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14804 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14805 { # const Typedef
14806 return ();
14807 }
14808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014809 }
14810 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14811 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014812 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014813 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14814 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014815 {
14816 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14817 "Old_Value"=>$Type1_Base{"Name"},
14818 "New_Value"=>$Type2_Base{"Name"},
14819 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014820 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014821 }
14822 else
14823 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014824 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014825 { # format change
14826 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14827 "Old_Value"=>$Type1_Base{"Name"},
14828 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014829 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014830 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014831 }
14832 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14833 {
14834 %{$LocalProblems{$Prefix."_BaseType"}}=(
14835 "Old_Value"=>$Type1_Base{"Name"},
14836 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014837 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014838 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014839 }
14840 }
14841 }
14842 }
14843 elsif($Type1{"Name"} ne $Type2{"Name"})
14844 { # type change
14845 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14846 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014847 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014848 and $Type1_Pure{"Name"} eq "void")
14849 {
14850 %{$LocalProblems{"Return_Type_From_Void"}}=(
14851 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014852 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014853 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014854 elsif($Prefix eq "Return"
14855 and $Type2_Pure{"Name"} eq "void")
14856 {
14857 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14858 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014859 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014861 else
14862 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014863 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014864 and $Type1{"Size"} and $Type2{"Size"}
14865 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014866 {
14867 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14868 "Old_Value"=>$Type1{"Name"},
14869 "New_Value"=>$Type2{"Name"},
14870 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014871 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014872 }
14873 else
14874 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014875 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014876 { # format change
14877 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14878 "Old_Value"=>$Type1{"Name"},
14879 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014880 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014881 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014882 }
14883 elsif(tNameLock($Type1_Id, $Type2_Id))
14884 { # FIXME: correct this condition
14885 %{$LocalProblems{$Prefix."_Type"}}=(
14886 "Old_Value"=>$Type1{"Name"},
14887 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014888 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014889 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014890 }
14891 }
14892 }
14893 }
14894 }
14895 if($Type1_PLevel!=$Type2_PLevel)
14896 {
14897 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14898 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14899 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014900 if($Level eq "Source")
14901 {
14902 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014903 "Old_Value"=>$Type1_PLevel,
14904 "New_Value"=>$Type2_PLevel);
14905 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014906 else
14907 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014908 if($Type2_PLevel>$Type1_PLevel)
14909 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014910 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14911 "Old_Value"=>$Type1_PLevel,
14912 "New_Value"=>$Type2_PLevel);
14913 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014914 else
14915 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014916 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14917 "Old_Value"=>$Type1_PLevel,
14918 "New_Value"=>$Type2_PLevel);
14919 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014920 }
14921 }
14922 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014923 if($Type1_Pure{"Type"} eq "Array"
14924 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014925 { # base_type[N] -> base_type[N]
14926 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014927 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014928 foreach my $SubProblemType (keys(%SubProblems))
14929 {
14930 $SubProblemType=~s/_Type/_BaseType/g;
14931 next if(defined $LocalProblems{$SubProblemType});
14932 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14933 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14934 }
14935 }
14936 }
14937 return %LocalProblems;
14938}
14939
14940sub tNameLock($$)
14941{
14942 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014943 my $Changed = 0;
14944 if(differentDumps("G"))
14945 { # different GCC versions
14946 $Changed = 1;
14947 }
14948 elsif(differentDumps("V"))
14949 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014950 if(not checkDump(1, "2.20")
14951 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014952 { # latest names update
14953 # 2.6: added restrict qualifier
14954 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014955 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014956 $Changed = 1;
14957 }
14958 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014959
14960 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14961 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14962
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014963 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014964 { # different formats
14965 if($UseOldDumps)
14966 { # old dumps
14967 return 0;
14968 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014969
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014970 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14971 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014972
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014973 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014974 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014975 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014976 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014977 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014978 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014979 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014980 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014981 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14982 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14983 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014984 { # equal base types
14985 return 0;
14986 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014987
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014988 if(not checkDump(1, "2.13")
14989 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014990 { # broken array names in ABI dumps < 2.13
14991 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014992 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014993 return 0;
14994 }
14995 }
14996
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014997 if(not checkDump(1, "2.6")
14998 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014999 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015000 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015001 and $TN2=~/\brestrict\b/) {
15002 return 0;
15003 }
15004 }
15005
15006 if(not checkDump(1, "2.20")
15007 or not checkDump(2, "2.20"))
15008 { # added restrict attribute in 2.6
15009 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15010 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015011 return 0;
15012 }
15013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015014 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015015 else
15016 {
15017 # typedef struct {...} type_t
15018 # typedef struct type_t {...} type_t
15019 if(index($TN1, " ".$TN2)!=-1)
15020 {
15021 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15022 return 0;
15023 }
15024 }
15025 if(index($TN2, " ".$TN1)!=-1)
15026 {
15027 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15028 return 0;
15029 }
15030 }
15031 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015032 return 1;
15033}
15034
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015035sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015036{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015037 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015038 if(defined $Cache{"differentDumps"}{$Check}) {
15039 return $Cache{"differentDumps"}{$Check};
15040 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015041 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015042 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015043 if($Check eq "G")
15044 {
15045 if(getGccVersion(1) ne getGccVersion(2))
15046 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015047 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015048 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015049 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015050 if($Check eq "V")
15051 {
15052 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15053 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15054 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015055 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015056 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015057 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015058 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015059 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015060}
15061
15062sub formatVersion($$)
15063{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015064 my ($V, $Digits) = @_;
15065 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015066 return join(".", splice(@Elems, 0, $Digits));
15067}
15068
15069sub htmlSpecChars($)
15070{
15071 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015072 if(not $Str) {
15073 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015074 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015075 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15076 $Str=~s/</&lt;/g;
15077 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15078 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015079 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15080 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015081 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015082 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015083 $Str=~s/\n/<br\/>/g;
15084 $Str=~s/\"/&quot;/g;
15085 $Str=~s/\'/&#39;/g;
15086 return $Str;
15087}
15088
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015089sub xmlSpecChars($)
15090{
15091 my $Str = $_[0];
15092 if(not $Str) {
15093 return $Str;
15094 }
15095
15096 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15097 $Str=~s/</&lt;/g;
15098 $Str=~s/>/&gt;/g;
15099
15100 $Str=~s/\"/&quot;/g;
15101 $Str=~s/\'/&#39;/g;
15102
15103 return $Str;
15104}
15105
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015106sub xmlSpecChars_R($)
15107{
15108 my $Str = $_[0];
15109 if(not $Str) {
15110 return $Str;
15111 }
15112
15113 $Str=~s/&amp;/&/g;
15114 $Str=~s/&lt;/</g;
15115 $Str=~s/&gt;/>/g;
15116
15117 $Str=~s/&quot;/"/g;
15118 $Str=~s/&#39;/'/g;
15119
15120 return $Str;
15121}
15122
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015123sub black_name($)
15124{
15125 my $Name = $_[0];
15126 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15127}
15128
15129sub highLight_Signature($)
15130{
15131 my $Signature = $_[0];
15132 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15133}
15134
15135sub highLight_Signature_Italic_Color($)
15136{
15137 my $Signature = $_[0];
15138 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15139}
15140
15141sub separate_symbol($)
15142{
15143 my $Symbol = $_[0];
15144 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15145 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15146 ($Name, $Spec, $Ver) = ($1, $2, $3);
15147 }
15148 return ($Name, $Spec, $Ver);
15149}
15150
15151sub cut_f_attrs($)
15152{
15153 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15154 return $2;
15155 }
15156 return "";
15157}
15158
15159sub highLight_Signature_PPos_Italic($$$$$)
15160{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015161 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15162 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015163 if($CheckObjectsOnly) {
15164 $ItalicParams=$ColorParams=0;
15165 }
15166 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15167 my $Return = "";
15168 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15169 $Return = $2;
15170 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015171 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015172 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015173 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015174 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015175 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015176 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015177 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015178 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015179 }
15180 return $Signature;
15181 }
15182 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15183 $Begin.=" " if($Begin!~/ \Z/);
15184 $End = cut_f_attrs($Signature);
15185 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015186 my ($Short, $Params) = split_Signature($Signature);
15187 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015188 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015189 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015190 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015191 $Part=~s/\A\s+|\s+\Z//g;
15192 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15193 if($Part=~/\([\*]+(\w+)\)/i) {
15194 $ParamName = $1;#func-ptr
15195 }
15196 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15197 $ParamName = $1;
15198 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015199 if(not $ParamName)
15200 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015201 push(@Parts, $Part_Styled);
15202 next;
15203 }
15204 if($ItalicParams and not $TName_Tid{1}{$Part}
15205 and not $TName_Tid{2}{$Part})
15206 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015207 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015208 if($Param_Pos ne ""
15209 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015210 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015211 }
15212 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015213 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015214 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015215 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015216 }
15217 $Part_Styled=~s/,(\w)/, $1/g;
15218 push(@Parts, $Part_Styled);
15219 }
15220 if(@Parts)
15221 {
15222 foreach my $Num (0 .. $#Parts)
15223 {
15224 if($Num==$#Parts)
15225 { # add ")" to the last parameter
15226 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15227 }
15228 elsif(length($Parts[$Num])<=45) {
15229 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15230 }
15231 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015232 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015233 }
15234 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015235 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015236 }
15237 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015238 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015239 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015240 $Signature=~s!\[\]![&#160;]!g;
15241 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015242 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15243 if($SymbolVersion) {
15244 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15245 }
15246 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015247}
15248
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015249sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015250{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015251 my $Signature = $_[0];
15252 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15253 {
15254 $Signature=~s/\A\Q$ShortName\E\(//g;
15255 cut_f_attrs($Signature);
15256 $Signature=~s/\)\Z//;
15257 return ($ShortName, $Signature);
15258 }
15259
15260 # error
15261 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015262}
15263
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015264sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015265{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015266 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015267 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015268 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15269 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015270 foreach my $Pos (0 .. length($Params) - 1)
15271 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015272 my $S = substr($Params, $Pos, 1);
15273 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015274 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015275 }
15276 if($S eq "," and
15277 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015278 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015279 if($Comma)
15280 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015281 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015282 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015283 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015284 }
15285 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015286 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015287 }
15288 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015289 if(not $Sp)
15290 { # remove spaces
15291 foreach (@Parts)
15292 {
15293 s/\A //g;
15294 s/ \Z//g;
15295 }
15296 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015297 return @Parts;
15298}
15299
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015300sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015301{
15302 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015303 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015304 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015305 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15306 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015307 $Center+=length($1);
15308 }
15309 foreach my $Pos (0 .. length($Sign)-1)
15310 {
15311 my $S = substr($Sign, $Pos, 1);
15312 if($S eq $Target)
15313 {
15314 if($B{"("}==$B{")"}
15315 and $B{"<"}==$B{">"}) {
15316 return $Center;
15317 }
15318 }
15319 if(defined $B{$S}) {
15320 $B{$S}+=1;
15321 }
15322 $Center+=1;
15323 }
15324 return 0;
15325}
15326
15327sub appendFile($$)
15328{
15329 my ($Path, $Content) = @_;
15330 return if(not $Path);
15331 if(my $Dir = get_dirname($Path)) {
15332 mkpath($Dir);
15333 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015334 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015335 print FILE $Content;
15336 close(FILE);
15337}
15338
15339sub writeFile($$)
15340{
15341 my ($Path, $Content) = @_;
15342 return if(not $Path);
15343 if(my $Dir = get_dirname($Path)) {
15344 mkpath($Dir);
15345 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015346 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015347 print FILE $Content;
15348 close(FILE);
15349}
15350
15351sub readFile($)
15352{
15353 my $Path = $_[0];
15354 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015355 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015356 local $/ = undef;
15357 my $Content = <FILE>;
15358 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015359 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015360 $Content=~s/\r/\n/g;
15361 }
15362 return $Content;
15363}
15364
15365sub get_filename($)
15366{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015367 if(defined $Cache{"get_filename"}{$_[0]}) {
15368 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015369 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015370 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15371 return ($Cache{"get_filename"}{$_[0]}=$1);
15372 }
15373 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015374}
15375
15376sub get_dirname($)
15377{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015378 if(defined $Cache{"get_dirname"}{$_[0]}) {
15379 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015380 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015381 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15382 return ($Cache{"get_dirname"}{$_[0]}=$1);
15383 }
15384 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015385}
15386
15387sub separate_path($) {
15388 return (get_dirname($_[0]), get_filename($_[0]));
15389}
15390
15391sub esc($)
15392{
15393 my $Str = $_[0];
15394 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15395 return $Str;
15396}
15397
15398sub readLineNum($$)
15399{
15400 my ($Path, $Num) = @_;
15401 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015402 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015403 foreach (1 ... $Num) {
15404 <FILE>;
15405 }
15406 my $Line = <FILE>;
15407 close(FILE);
15408 return $Line;
15409}
15410
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015411sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015412{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015413 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015414 return () if(not $Path or not -f $Path);
15415 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015416 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15417 {
15418 foreach my $AttrVal (split(/;/, $1))
15419 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015420 if($AttrVal=~/(.+):(.+)/)
15421 {
15422 my ($Name, $Value) = ($1, $2);
15423 $Attributes{$Name} = $Value;
15424 }
15425 }
15426 }
15427 return \%Attributes;
15428}
15429
15430sub is_abs($) {
15431 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15432}
15433
15434sub get_abs_path($)
15435{ # abs_path() should NOT be called for absolute inputs
15436 # because it can change them
15437 my $Path = $_[0];
15438 if(not is_abs($Path)) {
15439 $Path = abs_path($Path);
15440 }
15441 return $Path;
15442}
15443
15444sub get_OSgroup()
15445{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015446 my $N = $Config{"osname"};
15447 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015448 return "macos";
15449 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015450 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015451 return "bsd";
15452 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015453 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015454 return "beos";
15455 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015456 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015457 return "symbian";
15458 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015459 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015460 return "windows";
15461 }
15462 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015463 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015464 }
15465}
15466
15467sub getGccVersion($)
15468{
15469 my $LibVersion = $_[0];
15470 if($GCC_VERSION{$LibVersion})
15471 { # dump version
15472 return $GCC_VERSION{$LibVersion};
15473 }
15474 elsif($UsedDump{$LibVersion}{"V"})
15475 { # old-version dumps
15476 return "unknown";
15477 }
15478 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15479 if(not $GccVersion) {
15480 return "unknown";
15481 }
15482 return $GccVersion;
15483}
15484
15485sub showArch($)
15486{
15487 my $Arch = $_[0];
15488 if($Arch eq "arm"
15489 or $Arch eq "mips") {
15490 return uc($Arch);
15491 }
15492 return $Arch;
15493}
15494
15495sub getArch($)
15496{
15497 my $LibVersion = $_[0];
15498 if($CPU_ARCH{$LibVersion})
15499 { # dump version
15500 return $CPU_ARCH{$LibVersion};
15501 }
15502 elsif($UsedDump{$LibVersion}{"V"})
15503 { # old-version dumps
15504 return "unknown";
15505 }
15506 if(defined $Cache{"getArch"}{$LibVersion}) {
15507 return $Cache{"getArch"}{$LibVersion};
15508 }
15509 my $Arch = get_dumpmachine($GCC_PATH); # host version
15510 if(not $Arch) {
15511 return "unknown";
15512 }
15513 if($Arch=~/\A([\w]{3,})(-|\Z)/) {
15514 $Arch = $1;
15515 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040015516 $Arch = "x86" if($Arch=~/\Ai[3-7]86\Z/i);
15517 $Arch = "x86_64" if($Arch=~/\Aamd64\Z/i);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040015518 if($OSgroup eq "windows")
15519 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015520 $Arch = "x86" if($Arch=~/win32|mingw32/i);
15521 $Arch = "x86_64" if($Arch=~/win64|mingw64/i);
15522 }
15523 $Cache{"getArch"}{$LibVersion} = $Arch;
15524 return $Arch;
15525}
15526
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015527sub get_Report_Header($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015528{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015529 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015530 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015531 if(getArch(1) ne getArch(2)
15532 or getArch(1) eq "unknown"
15533 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015534 { # don't show architecture in the header
15535 $ArchInfo="";
15536 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015537 my $Report_Header = "<h1><span class='nowrap'>";
15538 if($Level eq "Source") {
15539 $Report_Header .= "Source compatibility";
15540 }
15541 elsif($Level eq "Binary") {
15542 $Report_Header .= "Binary compatibility";
15543 }
15544 else {
15545 $Report_Header .= "API compatibility";
15546 }
15547 $Report_Header .= " report for the <span style='color:Blue;'>$TargetLibraryFName</span> $TargetComponent</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015548 $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>";
15549 if($AppPath) {
15550 $Report_Header .= " <span class='nowrap'>&#160;(relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)</span>";
15551 }
15552 $Report_Header .= "</h1>\n";
15553 return $Report_Header;
15554}
15555
15556sub get_SourceInfo()
15557{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015558 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015559 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015560 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015561 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015562 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015563 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15564 $CheckedHeaders .= "<div class='h_list'>\n";
15565 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15566 {
15567 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15568 my $Name = get_filename($Identity);
15569 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15570 $CheckedHeaders .= $Name.$Comment."<br/>\n";
15571 }
15572 $CheckedHeaders .= "</div>\n";
15573 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015574 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015575
15576 if(my @Sources = keys(%{$Registered_Sources{1}}))
15577 {
15578 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15579 $CheckedSources .= "<div class='h_list'>\n";
15580 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15581 {
15582 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15583 my $Name = get_filename($Identity);
15584 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15585 $CheckedSources .= $Name.$Comment."<br/>\n";
15586 }
15587 $CheckedSources .= "</div>\n";
15588 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015590 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015591 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015592 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015593 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015594 $CheckedLibs .= "<div class='lib_list'>\n";
15595 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15596 {
15597 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15598 $CheckedLibs .= $Library."<br/>\n";
15599 }
15600 $CheckedLibs .= "</div>\n";
15601 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015602 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015603 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15604}
15605
15606sub get_ObjTitle()
15607{
15608 if(defined $UsedDump{1}{"DWARF"}) {
15609 return "Objects";
15610 }
15611 else {
15612 return ucfirst($SLIB_TYPE)." Libraries";
15613 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015614}
15615
15616sub get_TypeProblems_Count($$$)
15617{
15618 my ($TypeChanges, $TargetPriority, $Level) = @_;
15619 my $Type_Problems_Count = 0;
15620 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15621 {
15622 my %Kinds_Target = ();
15623 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15624 {
15625 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15626 {
15627 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015628 my $Priority = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015629 next if($Priority ne $TargetPriority);
15630 if($Kinds_Target{$Kind}{$Target}) {
15631 next;
15632 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015633 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015634 { # select a problem with the highest priority
15635 next;
15636 }
15637 $Kinds_Target{$Kind}{$Target} = 1;
15638 $Type_Problems_Count += 1;
15639 }
15640 }
15641 }
15642 return $Type_Problems_Count;
15643}
15644
15645sub get_Summary($)
15646{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015647 my $Level = $_[0];
15648 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015649 $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 +040015650 %{$RESULT{$Level}} = (
15651 "Problems"=>0,
15652 "Warnings"=>0,
15653 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015654 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015655 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015656 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015657 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015658 {
15659 if(not defined $CompatRules{$Level}{$Kind})
15660 { # unknown rule
15661 if(not $UnknownRules{$Level}{$Kind})
15662 { # only one warning
15663 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15664 $UnknownRules{$Level}{$Kind}=1;
15665 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015666 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015667 }
15668 }
15669 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015670 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15671 {
15672 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15673 {
15674 if(not defined $CompatRules{$Level}{$Kind})
15675 { # unknown rule
15676 if(not $UnknownRules{$Level}{$Kind})
15677 { # only one warning
15678 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15679 $UnknownRules{$Level}{$Kind}=1;
15680 }
15681 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15682 }
15683 }
15684 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015685 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015686 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015687 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015688 {
15689 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15690 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015691 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015692 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015693 my $Priority = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015694 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015695 $Added += 1;
15696 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015697 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015698 {
15699 $Removed += 1;
15700 $TotalAffected{$Level}{$Interface} = $Priority;
15701 }
15702 else
15703 {
15704 if($Priority eq "Safe") {
15705 $I_Other += 1;
15706 }
15707 elsif($Priority eq "High") {
15708 $I_Problems_High += 1;
15709 }
15710 elsif($Priority eq "Medium") {
15711 $I_Problems_Medium += 1;
15712 }
15713 elsif($Priority eq "Low") {
15714 $I_Problems_Low += 1;
15715 }
15716 if(($Priority ne "Low" or $StrictCompat)
15717 and $Priority ne "Safe") {
15718 $TotalAffected{$Level}{$Interface} = $Priority;
15719 }
15720 }
15721 }
15722 }
15723 }
15724 }
15725 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015726 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015727 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015728 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015729 {
15730 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15731 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015732 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015733 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015734 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15735 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015736 my $Priority = $CompatRules{$Level}{$Kind}{"Severity"};
15737 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15738
15739 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Priority})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015740 { # select a problem with the highest priority
15741 next;
15742 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015743
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015744 if(($Priority ne "Low" or $StrictCompat)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015745 and $Priority ne "Safe")
15746 {
15747 if(defined $TotalAffected{$Level}{$Interface})
15748 {
15749 if($Severity_Val{$Priority}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15750 $TotalAffected{$Level}{$Interface} = $Priority;
15751 }
15752 }
15753 else {
15754 $TotalAffected{$Level}{$Interface} = $Priority;
15755 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015756 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015757
15758 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15759
15760 if($MaxSeverity)
15761 {
15762 if($Severity_Val{$Priority}>$Severity_Val{$MaxSeverity}) {
15763 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Priority;
15764 }
15765 }
15766 else {
15767 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Priority;
15768 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015769 }
15770 }
15771 }
15772 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015773
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015774 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15775 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15776 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15777 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015778
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015779 %TypeChanges = (); # free memory
15780
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015781 if($CheckObjectsOnly)
15782 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015783 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015784 }
15785 else
15786 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015787 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015788 if($ExtendedCheck)
15789 { # don't count external_func_0 for constants
15790 $SCount-=1;
15791 }
15792 if($SCount)
15793 {
15794 my %Weight = (
15795 "High" => 100,
15796 "Medium" => 50,
15797 "Low" => 25
15798 );
15799 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015800 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015801 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015802 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015803 }
15804 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015805 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015806 }
15807 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015808 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15809 if($RESULT{$Level}{"Affected"}>=100) {
15810 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015811 }
15812
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015813 $RESULT{$Level}{"Problems"} += $Removed;
15814 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015815 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015816 if($StrictCompat) {
15817 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15818 }
15819 else {
15820 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015822
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015823 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015824 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015825 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015826 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015827 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015828 if($Severity eq "Safe")
15829 {
15830 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015831 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015832 elsif($Severity eq "Low")
15833 {
15834 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015835 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015836 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015837 }
15838
15839 if($C_Problems_Low)
15840 {
15841 if($StrictCompat) {
15842 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15843 }
15844 else {
15845 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015846 }
15847 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015848 if($CheckImpl and $Level eq "Binary")
15849 {
15850 if($StrictCompat) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015851 $RESULT{$Level}{"Problems"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015852 }
15853 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015854 $RESULT{$Level}{"Warnings"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015855 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015856 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015857 if($RESULT{$Level}{"Problems"}
15858 and $RESULT{$Level}{"Affected"}) {
15859 $RESULT{$Level}{"Verdict"} = "incompatible";
15860 }
15861 else {
15862 $RESULT{$Level}{"Verdict"} = "compatible";
15863 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015864
15865 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15866 if(not $TotalTypes)
15867 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015868 $TotalTypes = keys(%{$TName_Tid{1}});
15869 }
15870
15871 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15872 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15873
15874 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15875
15876 if($ReportFormat eq "xml")
15877 { # XML
15878 # test info
15879 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15880 $TestInfo .= " <version1>\n";
15881 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
15882 $TestInfo .= " <architecture>$Arch1</architecture>\n";
15883 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15884 $TestInfo .= " </version1>\n";
15885
15886 $TestInfo .= " <version2>\n";
15887 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
15888 $TestInfo .= " <architecture>$Arch2</architecture>\n";
15889 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15890 $TestInfo .= " </version2>\n";
15891 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15892
15893 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015894 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015895 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015896 $TestResults .= " <headers>\n";
15897 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15898 {
15899 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15900 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15901 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15902 }
15903 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015904 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015905
15906 if(my @Sources = keys(%{$Registered_Sources{1}}))
15907 {
15908 $TestResults .= " <sources>\n";
15909 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15910 {
15911 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15912 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15913 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15914 }
15915 $TestResults .= " </sources>\n";
15916 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015917
15918 $TestResults .= " <libs>\n";
15919 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15920 {
15921 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15922 $TestResults .= " <name>$Library</name>\n";
15923 }
15924 $TestResults .= " </libs>\n";
15925
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015926 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015927 $TestResults .= " <types>".$TotalTypes."</types>\n";
15928
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015929 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15930 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015931 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15932
15933 # problem summary
15934 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15935 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15936
15937 $Problem_Summary .= " <problems_with_types>\n";
15938 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15939 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15940 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15941 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15942 $Problem_Summary .= " </problems_with_types>\n";
15943
15944 $Problem_Summary .= " <problems_with_symbols>\n";
15945 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15946 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15947 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015948 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015949 $Problem_Summary .= " </problems_with_symbols>\n";
15950
15951 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015952 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015953 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015954 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015955 {
15956 $Problem_Summary .= " <impl>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015957 $Problem_Summary .= " <low>".keys(%CompatProblems_Impl)."</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015958 $Problem_Summary .= " </impl>\n";
15959 }
15960 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15961
15962 return ($TestInfo.$TestResults.$Problem_Summary, "");
15963 }
15964 else
15965 { # HTML
15966 # test info
15967 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015968 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015969 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetLibraryFName</td></tr>\n";
15970
15971 my (@VInf1, @VInf2, $AddTestInfo) = ();
15972 if($Arch1 ne "unknown"
15973 and $Arch2 ne "unknown")
15974 { # CPU arch
15975 if($Arch1 eq $Arch2)
15976 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015977 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015978 }
15979 else
15980 { # go to the version number
15981 push(@VInf1, showArch($Arch1));
15982 push(@VInf2, showArch($Arch2));
15983 }
15984 }
15985 if($GccV1 ne "unknown"
15986 and $GccV2 ne "unknown"
15987 and $OStarget ne "windows")
15988 { # GCC version
15989 if($GccV1 eq $GccV2)
15990 { # go to the separate section
15991 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15992 }
15993 else
15994 { # go to the version number
15995 push(@VInf1, "gcc ".$GccV1);
15996 push(@VInf2, "gcc ".$GccV2);
15997 }
15998 }
15999 # show long version names with GCC version and CPU architecture name (if different)
16000 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16001 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16002 $TestInfo .= $AddTestInfo;
16003 #if($COMMON_LANGUAGE{1}) {
16004 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16005 #}
16006 if($ExtendedCheck) {
16007 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16008 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016009 if($JoinReport)
16010 {
16011 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016012 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016013 }
16014 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016015 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016016 }
16017 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016018 $TestInfo .= "</table>\n";
16019
16020 # test results
16021 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016022 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016023
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016024 if(my @Headers = keys(%{$Registered_Headers{1}}))
16025 {
16026 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16027 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16028 }
16029 elsif($CheckObjectsOnly) {
16030 $TestResults .= "<tr><th>Total Header Files</th><td>0&#160;(not&#160;analyzed)</td></tr>\n";
16031 }
16032
16033 if(my @Sources = keys(%{$Registered_Sources{1}}))
16034 {
16035 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16036 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16037 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016038
16039 if(not $ExtendedCheck)
16040 {
16041 my $Libs_Link = "0";
16042 $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 +040016043 $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 +040016044 }
16045
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016046 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016047
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016048 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016049 if($JoinReport) {
16050 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16051 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016052 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016053 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016054 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
16055 }
16056 else {
16057 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
16058 }
16059 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016060 $TestResults .= "</table>\n";
16061
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016062 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016063 # problem summary
16064 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016065 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016066 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16067
16068 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016069 if($Added>0)
16070 {
16071 if($JoinReport) {
16072 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16073 }
16074 else {
16075 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16076 }
16077 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016078 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016079 $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 +040016080
16081 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016082 if($Removed>0)
16083 {
16084 if($JoinReport) {
16085 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16086 }
16087 else {
16088 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16089 }
16090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016091 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016092 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
16093 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016094
16095 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016096 $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 +040016097 $TH_Link = "n/a" if($CheckObjectsOnly);
16098 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016099 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
16100 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016101
16102 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016103 $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 +040016104 $TM_Link = "n/a" if($CheckObjectsOnly);
16105 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016106 $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 +040016107
16108 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016109 $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 +040016110 $TL_Link = "n/a" if($CheckObjectsOnly);
16111 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016112 $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 +040016113
16114 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016115 $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 +040016116 $IH_Link = "n/a" if($CheckObjectsOnly);
16117 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016118 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
16119 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016120
16121 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016122 $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 +040016123 $IM_Link = "n/a" if($CheckObjectsOnly);
16124 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016125 $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 +040016126
16127 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016128 $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 +040016129 $IL_Link = "n/a" if($CheckObjectsOnly);
16130 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016131 $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 +040016132
16133 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016134 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16135 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016136 }
16137 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016138 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016139 $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 +040016140
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016141 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016142 {
16143 my $ChangedImpl_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016144 $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 +040016145 $ChangedImpl_Link = "n/a" if($CheckHeadersOnly);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016146 $META_DATA .= "changed_implementation:".keys(%CompatProblems_Impl).";";
16147 $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 +040016148 }
16149 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016150 if($T_Other and not $CheckObjectsOnly)
16151 {
16152 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016153 $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 +040016154 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016155
16156 if($I_Other and not $CheckObjectsOnly)
16157 {
16158 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016159 $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 +040016160 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016161
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016162 if($C_Other and not $CheckObjectsOnly)
16163 {
16164 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16165 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
16166 }
16167
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016168 $META_DATA .= "tool_version:$TOOL_VERSION";
16169 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016170 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016171 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16172 }
16173}
16174
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016175sub getStyle($$$)
16176{
16177 my ($Subj, $Act, $Num) = @_;
16178 my %Style = (
16179 "A"=>"new",
16180 "R"=>"failed",
16181 "S"=>"passed",
16182 "L"=>"warning",
16183 "M"=>"failed",
16184 "H"=>"failed"
16185 );
16186 if($Num>0) {
16187 return " class='".$Style{$Act}."'";
16188 }
16189 return "";
16190}
16191
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016192sub show_number($)
16193{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016194 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016195 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016196 my $Num = cut_off_number($_[0], 2, 0);
16197 if($Num eq "0")
16198 {
16199 foreach my $P (3 .. 7)
16200 {
16201 $Num = cut_off_number($_[0], $P, 1);
16202 if($Num ne "0") {
16203 last;
16204 }
16205 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016206 }
16207 if($Num eq "0") {
16208 $Num = $_[0];
16209 }
16210 return $Num;
16211 }
16212 return $_[0];
16213}
16214
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016215sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016216{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016217 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016218 if($num!~/\./)
16219 {
16220 $num .= ".";
16221 foreach (1 .. $digs_to_cut-1) {
16222 $num .= "0";
16223 }
16224 }
16225 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16226 {
16227 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16228 $num .= "0";
16229 }
16230 }
16231 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16232 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16233 }
16234 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016235 if($z) {
16236 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016238 return $num;
16239}
16240
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016241sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016242{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016243 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016244 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016245
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016246 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016247 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16248 {
16249 my $Header = $Constants{1}{$Constant}{"Header"};
16250 if(not $Header)
16251 { # added
16252 $Header = $Constants{2}{$Constant}{"Header"}
16253 }
16254
16255 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16256 {
16257 if(not defined $CompatRules{$Level}{$Kind}) {
16258 next;
16259 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016260 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016261 next;
16262 }
16263 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16264 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016265 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016266
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016267 if($ReportFormat eq "xml")
16268 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016269 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016270 {
16271 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016272 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016273 {
16274 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016275 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16276 {
16277 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16278 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16279 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016280
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016281 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16282 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16283 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
16284 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16285 $CHANGED_CONSTANTS .= " </problem>\n";
16286 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016287 $CHANGED_CONSTANTS .= " </constant>\n";
16288 }
16289 $CHANGED_CONSTANTS .= " </header>\n";
16290 }
16291 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16292 }
16293 else
16294 { # HTML
16295 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016296 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016297 {
16298 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016299 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016300 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016301 my $Report = "";
16302
16303 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16304 {
16305 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16306 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16307 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16308 $Number += 1;
16309 }
16310 if($Report)
16311 {
16312 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16313 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16314 $Report = insertIDs($Report);
16315 }
16316 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016317 }
16318 $CHANGED_CONSTANTS .= "<br/>\n";
16319 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016320 if($CHANGED_CONSTANTS)
16321 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016322 my $Title = "Problems with Constants, $TargetSeverity Severity";
16323 if($TargetSeverity eq "Safe")
16324 { # Safe Changes
16325 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016326 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016327 $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 +040016328 }
16329 }
16330 return $CHANGED_CONSTANTS;
16331}
16332
16333sub get_Report_Impl()
16334{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016335 my $CHANGED_IMPLEMENTATION = "";
16336 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016337 foreach my $Interface (sort keys(%CompatProblems_Impl))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016338 {
16339 my $HeaderName = $CompleteSignature{1}{$Interface}{"Header"};
16340 my $DyLib = $Symbol_Library{1}{$Interface};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016341 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016342 }
16343 my $Changed_Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016344 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016345 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016346 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016347 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016348 my %NameSpaceSymbols = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016349 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016350 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016351 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016352 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016353 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016354 $CHANGED_IMPLEMENTATION .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016355 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016356 foreach my $Interface (@SortedInterfaces)
16357 {
16358 $Changed_Number += 1;
16359 my $Signature = get_Signature($Interface, 1);
16360 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016361 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016362 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016363 $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 +040016364 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016365 $CHANGED_IMPLEMENTATION .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016366 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016367 }
16368 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016369 if($CHANGED_IMPLEMENTATION)
16370 {
16371 $CHANGED_IMPLEMENTATION = insertIDs($CHANGED_IMPLEMENTATION);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016372 $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 +040016373 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016374
16375 # clean memory
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016376 %CompatProblems_Impl = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016377
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016378 return $CHANGED_IMPLEMENTATION;
16379}
16380
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016381sub getTitle($$$)
16382{
16383 my ($Header, $Library, $NameSpace) = @_;
16384 my $Title = "";
16385 if($Library and $Library!~/\.\w+\Z/) {
16386 $Library .= " (.$LIB_EXT)";
16387 }
16388 if($Header and $Library)
16389 {
16390 $Title .= "<span class='h_name'>$Header</span>";
16391 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16392 }
16393 elsif($Library) {
16394 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16395 }
16396 elsif($Header) {
16397 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16398 }
16399 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016400 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016401 }
16402 return $Title;
16403}
16404
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016405sub get_Report_Added($)
16406{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016407 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016408 my $ADDED_INTERFACES = "";
16409 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016410 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016411 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016412 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016413 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016414 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016415 {
16416 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16417 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016418 if($Level eq "Source" and $ReportFormat eq "html")
16419 { # do not show library name in HTML report
16420 $DyLib = "";
16421 }
16422 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016423 }
16424 }
16425 }
16426 if($ReportFormat eq "xml")
16427 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016428 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016429 {
16430 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016431 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016432 {
16433 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016434 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016435 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16436 }
16437 $ADDED_INTERFACES .= " </library>\n";
16438 }
16439 $ADDED_INTERFACES .= " </header>\n";
16440 }
16441 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16442 }
16443 else
16444 { # HTML
16445 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016446 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016447 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016448 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016449 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016450 my %NameSpaceSymbols = ();
16451 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016452 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016453 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016454 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016455 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016456 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16457 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016458 foreach my $Interface (@SortedInterfaces)
16459 {
16460 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016461 my $Signature = get_Signature($Interface, 2);
16462 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016463 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016464 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016465 if($Interface=~/\A(_Z|\?)/)
16466 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016467 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016468 $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 +040016469 }
16470 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016471 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016472 }
16473 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016474 else
16475 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016476 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016477 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016478 }
16479 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016480 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016481 }
16482 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016483 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016484 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016485 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016486 }
16487 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016488 if($ADDED_INTERFACES)
16489 {
16490 my $Anchor = "<a name='Added'></a>";
16491 if($JoinReport) {
16492 $Anchor = "<a name='".$Level."_Added'></a>";
16493 }
16494 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016495 }
16496 }
16497 return $ADDED_INTERFACES;
16498}
16499
16500sub get_Report_Removed($)
16501{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016502 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016503 my $REMOVED_INTERFACES = "";
16504 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016505 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016506 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016507 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016508 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016509 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016510 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016511 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16512 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016513 if($Level eq "Source" and $ReportFormat eq "html")
16514 { # do not show library name in HTML report
16515 $DyLib = "";
16516 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016517 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016518 }
16519 }
16520 }
16521 if($ReportFormat eq "xml")
16522 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016523 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016524 {
16525 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016526 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016527 {
16528 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016529 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16530 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016531 }
16532 $REMOVED_INTERFACES .= " </library>\n";
16533 }
16534 $REMOVED_INTERFACES .= " </header>\n";
16535 }
16536 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16537 }
16538 else
16539 { # HTML
16540 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016541 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016542 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016543 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016544 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016545 my %NameSpaceSymbols = ();
16546 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016547 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016548 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016549 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016550 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016551 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16552 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016553 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016554 {
16555 $Removed_Number += 1;
16556 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016557 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016558 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016559 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016560 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016561 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016562 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016563 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016564 $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 +040016565 }
16566 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016567 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016568 }
16569 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016570 else
16571 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016572 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016573 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016574 }
16575 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016576 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016577 }
16578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016579 }
16580 }
16581 $REMOVED_INTERFACES .= "<br/>\n";
16582 }
16583 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016584 if($REMOVED_INTERFACES)
16585 {
16586 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16587 if($JoinReport) {
16588 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16589 }
16590 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016591 }
16592 }
16593 return $REMOVED_INTERFACES;
16594}
16595
16596sub getXmlParams($$)
16597{
16598 my ($Content, $Problem) = @_;
16599 return "" if(not $Content or not $Problem);
16600 my %XMLparams = ();
16601 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16602 {
16603 my $Macro = "\@".lc($Attr);
16604 if($Content=~/\Q$Macro\E/) {
16605 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16606 }
16607 }
16608 my @PString = ();
16609 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016610 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016611 }
16612 if(@PString) {
16613 return " ".join(" ", @PString);
16614 }
16615 else {
16616 return "";
16617 }
16618}
16619
16620sub addMarkup($)
16621{
16622 my $Content = $_[0];
16623 # auto-markup
16624 $Content=~s/\n[ ]*//; # spaces
16625 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16626 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016627 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016628 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16629 if($Content=~/\ANOTE:/)
16630 { # notes
16631 $Content=~s!(NOTE):!<b>$1</b>:!g;
16632 }
16633 else {
16634 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16635 }
16636 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16637 my @Keywords = (
16638 "void",
16639 "const",
16640 "static",
16641 "restrict",
16642 "volatile",
16643 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016644 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016645 );
16646 my $MKeys = join("|", @Keywords);
16647 foreach (@Keywords) {
16648 $MKeys .= "|non-".$_;
16649 }
16650 $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 +040016651
16652 # Markdown
16653 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16654 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016655 return $Content;
16656}
16657
16658sub applyMacroses($$$$)
16659{
16660 my ($Level, $Kind, $Content, $Problem) = @_;
16661 return "" if(not $Content or not $Problem);
16662 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16663 $Content = addMarkup($Content);
16664 # macros
16665 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16666 {
16667 my $Macro = "\@".lc($Attr);
16668 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016669 if(not defined $Value
16670 or $Value eq "") {
16671 next;
16672 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016673 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016674 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016675 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
16676 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016677 $Value = black_name($Value);
16678 }
16679 elsif($Value=~/\s/) {
16680 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16681 }
16682 elsif($Value=~/\A\d+\Z/
16683 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16684 { # bits to bytes
16685 if($Value % $BYTE_SIZE)
16686 { # bits
16687 if($Value==1) {
16688 $Value = "<b>".$Value."</b> bit";
16689 }
16690 else {
16691 $Value = "<b>".$Value."</b> bits";
16692 }
16693 }
16694 else
16695 { # bytes
16696 $Value /= $BYTE_SIZE;
16697 if($Value==1) {
16698 $Value = "<b>".$Value."</b> byte";
16699 }
16700 else {
16701 $Value = "<b>".$Value."</b> bytes";
16702 }
16703 }
16704 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016705 else
16706 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016707 $Value = "<b>".htmlSpecChars($Value)."</b>";
16708 }
16709 $Content=~s/\Q$Macro\E/$Value/g;
16710 }
16711
16712 if($Content=~/(\A|[^\@\w])\@\w/)
16713 {
16714 if(not $IncompleteRules{$Level}{$Kind})
16715 { # only one warning
16716 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16717 $IncompleteRules{$Level}{$Kind} = 1;
16718 }
16719 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016720 return $Content;
16721}
16722
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016723sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016724{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016725 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016726 my $INTERFACE_PROBLEMS = "";
16727 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016728 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016729 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016730 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16731 if($SV and defined $CompatProblems{$Level}{$SN}) {
16732 next;
16733 }
16734 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016735 {
16736 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016737 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016738 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016739 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16740 my $DyLib = $Symbol_Library{1}{$Symbol};
16741 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016742 { # Symbol with Version
16743 $DyLib = $Symbol_Library{1}{$VSym};
16744 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016745 if(not $DyLib)
16746 { # const global data
16747 $DyLib = "";
16748 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016749 if($Level eq "Source" and $ReportFormat eq "html")
16750 { # do not show library name in HTML report
16751 $DyLib = "";
16752 }
16753 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16754 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016755 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016756 my $Priority = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016757 if($Priority ne $TargetSeverity) {
16758 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016759 }
16760 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016761 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16762 {
16763 delete($SymbolChanges{$Symbol}{$Kind});
16764 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016765 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016766 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016767 }
16768 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016769 if(not keys(%{$SymbolChanges{$Symbol}})) {
16770 delete($SymbolChanges{$Symbol});
16771 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016772 }
16773 if($ReportFormat eq "xml")
16774 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016775 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016776 {
16777 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016778 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016779 {
16780 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016781 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 +040016782 {
16783 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16784 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16785 {
16786 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16787 {
16788 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016789 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016790
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016791 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16792 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16793 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16794 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16795 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
16796 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
16797 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16798 $INTERFACE_PROBLEMS .= " </problem>\n";
16799 }
16800 }
16801 $INTERFACE_PROBLEMS .= " </symbol>\n";
16802 }
16803 $INTERFACE_PROBLEMS .= " </library>\n";
16804 }
16805 $INTERFACE_PROBLEMS .= " </header>\n";
16806 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016807 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016808 }
16809 else
16810 { # HTML
16811 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016812 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016813 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016814 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016815 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016816 my (%NameSpaceSymbols, %NewSignature) = ();
16817 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016818 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016819 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016820 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016821 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016822 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016823 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 +040016824 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016825 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016826 my $Signature = get_Signature($Symbol, 1);
16827 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016828 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016829 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016830 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016831 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016832 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016833 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016834 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016835 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016836 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016837 }
16838 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16839 {
16840 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016841 $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 +040016842 $ProblemNum += 1;
16843 $ProblemsNum += 1;
16844 }
16845 }
16846 }
16847 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016848 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016849 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016850 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016851 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016852 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016853 }
16854 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016855 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016856 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016857 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16858 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16859 if($NewSignature{$Symbol})
16860 { # argument list changed to
16861 $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 +040016862 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016863 if($Symbol=~/\A(_Z|\?)/) {
16864 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16865 }
16866 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16867 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016868 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016869 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016870 }
16871 }
16872 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016873 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016874 }
16875 }
16876 }
16877 if($INTERFACE_PROBLEMS)
16878 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016879 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16880 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16881 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016882 { # Safe Changes
16883 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016884 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016885 $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 +040016886 }
16887 }
16888 return $INTERFACE_PROBLEMS;
16889}
16890
16891sub get_Report_TypeProblems($$)
16892{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016893 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016894 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016895 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016896 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016897 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016898 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016899 {
16900 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16901 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016902 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016903 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016904 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016905 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016906 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016907 if($Severity eq "Safe"
16908 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016909 next;
16910 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016911
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016912 if(cmpSeverities($Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target}, $Severity))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016913 { # select a problem with the highest priority
16914 next;
16915 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016916 %{$TypeChanges{$TypeName}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016917 }
16918 }
16919 }
16920 }
16921 my %Kinds_Locations = ();
16922 foreach my $TypeName (keys(%TypeChanges))
16923 {
16924 my %Kinds_Target = ();
16925 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16926 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016927 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016928 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016929 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016930 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016931 { # other priority
16932 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16933 next;
16934 }
16935 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16936 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
16937 if($Kinds_Target{$Kind}{$Target})
16938 { # duplicate target
16939 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16940 next;
16941 }
16942 $Kinds_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016943 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016944 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016945 }
16946 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16947 delete($TypeChanges{$TypeName}{$Kind});
16948 }
16949 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016950 if(not keys(%{$TypeChanges{$TypeName}})) {
16951 delete($TypeChanges{$TypeName});
16952 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016953 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016954 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 +040016955 if($ReportFormat eq "xml")
16956 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016957 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016958 {
16959 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016960 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016961 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016962 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016963 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16964 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016965 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016966 {
16967 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16968 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16969 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16970 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16971 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16972 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
16973 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
16974 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16975 $TYPE_PROBLEMS .= " </problem>\n";
16976 }
16977 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016978 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016979 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016980 $TYPE_PROBLEMS .= showVTables($TypeName);
16981 }
16982 $TYPE_PROBLEMS .= " </type>\n";
16983 }
16984 $TYPE_PROBLEMS .= " </header>\n";
16985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016986 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016987 }
16988 else
16989 { # HTML
16990 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016991 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016992 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016993 my (%NameSpace_Type) = ();
16994 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016995 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016996 }
16997 foreach my $NameSpace (sort keys(%NameSpace_Type))
16998 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016999 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017000 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 +040017001 foreach my $TypeName (@SortedTypes)
17002 {
17003 my $ProblemNum = 1;
17004 my $TYPE_REPORT = "";
17005 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
17006 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017007 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017008 {
17009 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
17010 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17011 {
17012 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
17013 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
17014 $ProblemNum += 1;
17015 $ProblemsNum += 1;
17016 }
17017 }
17018 }
17019 $ProblemNum -= 1;
17020 if($TYPE_REPORT)
17021 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017022 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017023 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017024 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017025 $ShowVTables = showVTables($TypeName);
17026 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017027
17028 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017029 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17030 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17031 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17032 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017033 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017034 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017035 }
17036 }
17037 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017038 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017039 }
17040 }
17041 if($TYPE_PROBLEMS)
17042 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017043 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17044 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017045 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017046 { # Safe Changes
17047 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017048 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017049 $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 +040017050 }
17051 }
17052 return $TYPE_PROBLEMS;
17053}
17054
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017055sub show_Type($$$)
17056{
17057 my ($Name, $Html, $LibVersion) = @_;
17058 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17059 $TType = lc($TType);
17060 if($TType=~/struct|union|enum/) {
17061 $Name=~s/\A\Q$TType\E //g;
17062 }
17063 if($Html) {
17064 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17065 }
17066 else {
17067 $Name = $TType." ".$Name;
17068 }
17069 return $Name;
17070}
17071
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017072sub get_Anchor($$$)
17073{
17074 my ($Kind, $Level, $Severity) = @_;
17075 if($JoinReport)
17076 {
17077 if($Severity eq "Safe") {
17078 return "Other_".$Level."_Changes_In_".$Kind."s";
17079 }
17080 else {
17081 return $Kind."_".$Level."_Problems_".$Severity;
17082 }
17083 }
17084 else
17085 {
17086 if($Severity eq "Safe") {
17087 return "Other_Changes_In_".$Kind."s";
17088 }
17089 else {
17090 return $Kind."_Problems_".$Severity;
17091 }
17092 }
17093}
17094
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017095sub showVTables($)
17096{
17097 my $TypeName = $_[0];
17098 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017099 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017100 if(defined $Type1{"VTable"}
17101 and keys(%{$Type1{"VTable"}}))
17102 {
17103 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017104 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017105 if(defined $Type2{"VTable"}
17106 and keys(%{$Type2{"VTable"}}))
17107 {
17108 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17109 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017110 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017111 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017112 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17113 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017114 }
17115 my $VTABLES = "";
17116 if($ReportFormat eq "xml")
17117 { # XML
17118 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017119 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017120 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017121 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017122 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17123 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017124 $VTABLES .= " </entry>\n";
17125 }
17126 $VTABLES .= " </vtable>\n\n";
17127 }
17128 else
17129 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017130 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017131 $VTABLES .= "<tr><th width='2%'>Offset</th>";
17132 $VTABLES .= "<th width='45%'>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
17133 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017134 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017135 {
17136 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017137 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017138 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017139 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017140 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017141 $Color1 = " class='failed'";
17142 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017143 }
17144 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017145 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017146 }
17147 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017148 $VTABLES .= "<tr><th>".$Index."</th>\n";
17149 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17150 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017151 }
17152 $VTABLES .= "</table><br/>\n";
17153 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017154 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017155 }
17156 return $VTABLES;
17157 }
17158 }
17159 return "";
17160}
17161
17162sub simpleVEntry($)
17163{
17164 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017165 if(not defined $VEntry
17166 or $VEntry eq "") {
17167 return "";
17168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017169 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17170 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17171 if($VEntry=~/\A_ZThn.+\Z/) {
17172 $VEntry = "non-virtual thunk";
17173 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017174 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017175 # support for old GCC versions
17176 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17177 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17178 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017179 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17180 return $VEntry;
17181}
17182
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017183sub adjustParamPos($$$)
17184{
17185 my ($Pos, $Symbol, $LibVersion) = @_;
17186 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17187 {
17188 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17189 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17190 {
17191 return $Pos-1;
17192 }
17193
17194 return $Pos;
17195 }
17196
17197 return undef;
17198}
17199
17200sub getParamPos($$$)
17201{
17202 my ($Name, $Symbol, $LibVersion) = @_;
17203
17204 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17205 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17206 {
17207 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17208 foreach (keys(%{$Info->{"Param"}}))
17209 {
17210 if($Info->{"Param"}{$_}{"name"} eq $Name)
17211 {
17212 return $_;
17213 }
17214 }
17215 }
17216
17217 return undef;
17218}
17219
17220sub getParamName($)
17221{
17222 my $Loc = $_[0];
17223 $Loc=~s/\->.*//g;
17224 return $Loc;
17225}
17226
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017227sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017228{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017229 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017230 my $LIMIT = 1000;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017231
17232 if(defined $AffectLimit)
17233 {
17234 $LIMIT = $AffectLimit;
17235 }
17236 else
17237 {
17238 if($#{$Syms}>=10000)
17239 { # reduce size of the report
17240 $LIMIT = 10;
17241 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017242 }
17243 my %SProblems = ();
17244 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017245 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017246 if(keys(%SProblems)>$LIMIT) {
17247 last;
17248 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017249 if(($Symbol=~/(C2|D2|D0)[EI]/))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017250 { # duplicated problems for C2 constructors, D2 and D0 destructors
17251 next;
17252 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017253 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17254 if($Level eq "Source")
17255 { # remove symbol version
17256 $Symbol=$SN;
17257 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017258 my ($MinPath_Length, $ProblemLocation_Last) = (-1, "");
17259 my $Severity_Max = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017260 my $Signature = get_Signature($Symbol, 1);
17261 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017262 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017263 foreach my $Location (keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017264 {
17265 if(not defined $Kinds_Locations->{$Kind}
17266 or not $Kinds_Locations->{$Kind}{$Location}) {
17267 next;
17268 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017269 if($SV and defined $CompatProblems{$Level}{$SN}
17270 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Location})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017271 { # duplicated problems for versioned symbols
17272 next;
17273 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017274 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017275 next if($Type_Name ne $Target_TypeName);
17276
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017277 my $PName = getParamName($Location);
17278 my $PPos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17279
17280 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017281 my $Path_Length = 0;
17282 my $ProblemLocation = $Location;
17283 if($Type_Name) {
17284 $ProblemLocation=~s/->\Q$Type_Name\E\Z//g;
17285 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017286 while($ProblemLocation=~/\-\>/g) {
17287 $Path_Length += 1;
17288 }
17289 if($MinPath_Length==-1 or ($Path_Length<=$MinPath_Length and $Severity_Val{$Severity}>$Severity_Max)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017290 or (cmpLocations($ProblemLocation, $ProblemLocation_Last) and $Severity_Val{$Severity}==$Severity_Max))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017291 {
17292 $MinPath_Length = $Path_Length;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017293 $Severity_Max = $Severity_Val{$Severity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017294 $ProblemLocation_Last = $ProblemLocation;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017295 %{$SProblems{$Symbol}} = (
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017296 "Descr"=>getAffectDesc($Level, $Symbol, $Kind, $Location),
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017297 "Severity_Max"=>$Severity_Max,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017298 "Signature"=>$Signature,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017299 "Position"=>$PPos,
17300 "Param_Name"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017301 "Location"=>$Location
17302 );
17303 }
17304 }
17305 }
17306 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017307 my @Symbols = keys(%SProblems);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017308 @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 +040017309 @Symbols = sort {$SProblems{$b}{"Severity_Max"}<=>$SProblems{$a}{"Severity_Max"}} @Symbols;
17310 if($#Symbols+1>$LIMIT)
17311 { # remove last element
17312 pop(@Symbols);
17313 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017314 my $Affected = "";
17315 if($ReportFormat eq "xml")
17316 { # XML
17317 $Affected .= " <affected>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017318 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017319 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017320 my $Param_Name = $SProblems{$Symbol}{"Param_Name"};
17321 my $Description = $SProblems{$Symbol}{"Descr"};
17322 my $Location = $SProblems{$Symbol}{"Location"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017323 my $Target = "";
17324 if($Param_Name) {
17325 $Target = " affected=\"param\" param_name=\"$Param_Name\"";
17326 }
17327 elsif($Location=~/\Aretval(\-|\Z)/i) {
17328 $Target = " affected=\"retval\"";
17329 }
17330 elsif($Location=~/\Athis(\-|\Z)/i) {
17331 $Target = " affected=\"this\"";
17332 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017333 $Affected .= " <symbol$Target name=\"$Symbol\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017334 $Affected .= " <comment>".xmlSpecChars($Description)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017335 $Affected .= " </symbol>\n";
17336 }
17337 $Affected .= " </affected>\n";
17338 }
17339 else
17340 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017341 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017342 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017343 my $Description = $SProblems{$Symbol}{"Descr"};
17344 my $Signature = $SProblems{$Symbol}{"Signature"};
17345 my $Pos = $SProblems{$Symbol}{"Position"};
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017346 $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 +040017347 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017348 if(keys(%SProblems)>$LIMIT) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017349 $Affected .= "and others ...<br/>";
17350 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017351 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017352 if($Affected)
17353 {
17354 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017355 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".(keys(%SProblems)>$LIMIT?">".$LIMIT:keys(%SProblems)).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017356 }
17357 }
17358 return $Affected;
17359}
17360
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017361sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017362{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017363 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017364 if($L2=~/\A(retval|this)\b/
17365 and $L1!~/\A(retval|this)\b/)
17366 {
17367 if($L1!~/\-\>/) {
17368 return 1;
17369 }
17370 elsif($L2=~/\-\>/) {
17371 return 1;
17372 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017373 }
17374 return 0;
17375}
17376
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017377sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017378{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017379 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017380
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017381 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017382
17383 my $Location_I = $Location;
17384 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17385
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017386 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017387
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017388 if($Kind eq "Overridden_Virtual_Method"
17389 or $Kind eq "Overridden_Virtual_Method_B") {
17390 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17391 }
17392 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17393 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017394 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17395
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017396 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17397 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017398 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17399 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17400
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017401 if($ClassName eq $Problem{"Type_Name"}) {
17402 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17403 }
17404 else {
17405 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17406 }
17407 }
17408 else
17409 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017410 my $TypeID = undef;
17411
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017412 if($Location=~/retval/)
17413 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017414 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017415 push(@Sentence, "Field \'".$Location."\' in return value");
17416 }
17417 else {
17418 push(@Sentence, "Return value");
17419 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017420
17421 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017422 }
17423 elsif($Location=~/this/)
17424 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017425 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017426 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17427 }
17428 else {
17429 push(@Sentence, "\'this\' pointer");
17430 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017431
17432 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017433 }
17434 else
17435 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017436
17437 my $PName = getParamName($Location);
17438 my $PPos = getParamPos($PName, $Symbol, 1);
17439
17440 if(index($Location, "->")!=-1) {
17441 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017442 }
17443 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017444 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017445 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017446 if($PName) {
17447 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017448 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017449
17450 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17451 }
17452
17453 if($Location!~/this/)
17454 {
17455 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017456 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017457 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017458 push(@Sentence, "(pointer)");
17459 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017460 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017461 push(@Sentence, "(reference)");
17462 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017463 }
17464 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017465
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017466 if($Location eq "this") {
17467 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17468 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017469 else
17470 {
17471 my $Location_T = $Location;
17472 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17473
17474 my $TypeID_Problem = $TypeID;
17475 if($Location_T) {
17476 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17477 }
17478
17479 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17480 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17481 }
17482 else {
17483 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17484 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017485 }
17486 }
17487 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017488 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017489 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 +040017490 }
17491 return join(" ", @Sentence);
17492}
17493
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017494sub getFieldType($$$)
17495{
17496 my ($Location, $TypeId, $LibVersion) = @_;
17497
17498 my @Fields = split("->", $Location);
17499
17500 foreach my $Name (@Fields)
17501 {
17502 my %Info = get_BaseType($TypeId, $LibVersion);
17503
17504 foreach my $Pos (keys(%{$Info{"Memb"}}))
17505 {
17506 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17507 {
17508 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17509 last;
17510 }
17511 }
17512 }
17513
17514 return $TypeId;
17515}
17516
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017517sub get_XmlSign($$)
17518{
17519 my ($Symbol, $LibVersion) = @_;
17520 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17521 my $Report = "";
17522 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17523 {
17524 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017525 my $Type = $Info->{"Param"}{$Pos}{"type"};
17526 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017527 foreach my $Typedef (keys(%ChangedTypedef))
17528 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017529 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17530 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17531 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017532 }
17533 $Report .= " <param pos=\"$Pos\">\n";
17534 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017535 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017536 $Report .= " </param>\n";
17537 }
17538 if(my $Return = $Info->{"Return"})
17539 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017540 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017541 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017542 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017543 $Report .= " </retval>\n";
17544 }
17545 return $Report;
17546}
17547
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017548sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017549{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017550 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017551 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017552 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017553 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017554 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17555 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017556 next;
17557 }
17558 $Report .= " <symbol name=\"$Symbol\">\n";
17559 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017560 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017561 {
17562 if(defined $CompleteSignature{1}{$Symbol}
17563 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17564 {
17565 $P1 = get_XmlSign($Symbol, 1);
17566 $S1 = get_Signature($Symbol, 1);
17567 }
17568 elsif($Symbol=~/\A(_Z|\?)/) {
17569 $S1 = $tr_name{$Symbol};
17570 }
17571 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017572 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017573 {
17574 if(defined $CompleteSignature{2}{$Symbol}
17575 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17576 {
17577 $P2 = get_XmlSign($Symbol, 2);
17578 $S2 = get_Signature($Symbol, 2);
17579 }
17580 elsif($Symbol=~/\A(_Z|\?)/) {
17581 $S2 = $tr_name{$Symbol};
17582 }
17583 }
17584 if($S1)
17585 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017586 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017587 $Report .= $P1;
17588 $Report .= " </old>\n";
17589 }
17590 if($S2 and $S2 ne $S1)
17591 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017592 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017593 $Report .= $P2;
17594 $Report .= " </new>\n";
17595 }
17596 $Report .= " </symbol>\n";
17597 }
17598 $Report .= "</symbols_info>\n";
17599 return $Report;
17600}
17601
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017602sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017603{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017604 my ($Level, $Report) = @_;
17605 if($ReportFormat eq "xml") {
17606 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017607 }
17608 if($StdOut)
17609 { # --stdout option
17610 print STDOUT $Report;
17611 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017612 else
17613 {
17614 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017615 mkpath(get_dirname($RPath));
17616
17617 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17618 print REPORT $Report;
17619 close(REPORT);
17620
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017621 if($Browse or $OpenReport)
17622 { # open in browser
17623 openReport($RPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017624 if($JoinReport or $DoubleReport)
17625 {
17626 if($Level eq "Binary")
17627 { # wait to open a browser
17628 sleep(1);
17629 }
17630 }
17631 }
17632 }
17633}
17634
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017635sub openReport($)
17636{
17637 my $Path = $_[0];
17638 my $Cmd = "";
17639 if($Browse)
17640 { # user-defined browser
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017641 $Cmd = $Browse." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017642 }
17643 if(not $Cmd)
17644 { # default browser
17645 if($OSgroup eq "macos") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017646 $Cmd = "open \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017647 }
17648 elsif($OSgroup eq "windows") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017649 $Cmd = "start ".path_format($Path, $OSgroup);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017650 }
17651 else
17652 { # linux, freebsd, solaris
17653 my @Browsers = (
17654 "x-www-browser",
17655 "sensible-browser",
17656 "firefox",
17657 "opera",
17658 "xdg-open",
17659 "lynx",
17660 "links"
17661 );
17662 foreach my $Br (@Browsers)
17663 {
17664 if($Br = get_CmdPath($Br))
17665 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017666 $Cmd = $Br." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017667 last;
17668 }
17669 }
17670 }
17671 }
17672 if($Cmd)
17673 {
17674 if($Debug) {
17675 printMsg("INFO", "running $Cmd");
17676 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017677 if($OSgroup ne "windows"
17678 and $OSgroup ne "macos")
17679 {
17680 if($Cmd!~/lynx|links/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017681 $Cmd .= " >\"/dev/null\" 2>&1 &";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017682 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017683 }
17684 system($Cmd);
17685 }
17686 else {
17687 printMsg("ERROR", "cannot open report in browser");
17688 }
17689}
17690
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017691sub getReport($)
17692{
17693 my $Level = $_[0];
17694 if($ReportFormat eq "xml")
17695 { # XML
17696
17697 if($Level eq "Join")
17698 {
17699 my $Report = "<reports>\n";
17700 $Report .= getReport("Binary");
17701 $Report .= getReport("Source");
17702 $Report .= "</reports>\n";
17703 return $Report;
17704 }
17705 else
17706 {
17707 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17708 my ($Summary, $MetaData) = get_Summary($Level);
17709 $Report .= $Summary."\n";
17710 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17711 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17712 $Report .= get_Report_SymbolsInfo($Level);
17713 $Report .= "</report>\n";
17714 return $Report;
17715 }
17716 }
17717 else
17718 { # HTML
17719 my $CssStyles = readModule("Styles", "Report.css");
17720 my $JScripts = readModule("Scripts", "Sections.js");
17721 if($Level eq "Join")
17722 {
17723 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17724 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017725 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
17726 my $Keywords = $TargetLibraryFName.", compatibility, API, report";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017727 my $Description = "Compatibility report for the $TargetLibraryFName $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
17728 my ($BSummary, $BMetaData) = get_Summary("Binary");
17729 my ($SSummary, $SMetaData) = get_Summary("Source");
17730 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>";
17731 $Report .= get_Report_Header("Join")."
17732 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017733 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17734 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017735 </div>";
17736 $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>";
17737 $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 +040017738 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017739 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17740 return $Report;
17741 }
17742 else
17743 {
17744 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017745 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17746 my $Keywords = $TargetLibraryFName.", ".lc($Level)." compatibility, API, report";
17747 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 +040017748 if($Level eq "Binary")
17749 {
17750 if(getArch(1) eq getArch(2)
17751 and getArch(1) ne "unknown") {
17752 $Description .= " on ".showArch(getArch(1));
17753 }
17754 }
17755 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."\n<body>\n<div><a name='Top'></a>\n";
17756 $Report .= get_Report_Header($Level)."\n".$Summary."\n";
17757 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17758 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17759 $Report .= get_SourceInfo();
17760 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017761 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017762 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17763 return $Report;
17764 }
17765 }
17766}
17767
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017768sub getLegend()
17769{
17770 return "<br/>
17771<table class='summary'>
17772<tr>
17773 <td class='new'>added</td>
17774 <td class='passed'>compatible</td>
17775</tr>
17776<tr>
17777 <td class='warning'>warning</td>
17778 <td class='failed'>incompatible</td>
17779</tr></table>\n";
17780}
17781
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017782sub createReport()
17783{
17784 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017785 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017786 writeReport("Join", getReport("Join"));
17787 }
17788 elsif($DoubleReport)
17789 { # default
17790 writeReport("Binary", getReport("Binary"));
17791 writeReport("Source", getReport("Source"));
17792 }
17793 elsif($BinaryOnly)
17794 { # --binary
17795 writeReport("Binary", getReport("Binary"));
17796 }
17797 elsif($SourceOnly)
17798 { # --source
17799 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017800 }
17801}
17802
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017803sub getReportFooter($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017804{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017805 my ($LibName, $Wide) = @_;
17806 my $FooterStyle = $Wide?"width:99%":"width:97%;padding-top:3px";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017807 my $Footer = "<div style='$FooterStyle;font-size:11px;' align='right'><i>Generated on ".(localtime time); # report date
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017808 $Footer .= " for <span style='font-weight:bold'>$LibName</span>"; # tested library/system name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017809 $Footer .= " by <a href='".$HomePage{"Wiki"}."'>ABI Compliance Checker</a>"; # tool name
17810 my $ToolSummary = "<br/>A tool for checking backward compatibility of a C/C++ library API&#160;&#160;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017811 $Footer .= " $TOOL_VERSION &#160;$ToolSummary</i></div>"; # tool version
17812 return $Footer;
17813}
17814
17815sub get_Report_Problems($$)
17816{
17817 my ($Priority, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017818 my $Report = get_Report_TypeProblems($Priority, $Level);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017819 if(my $SProblems = get_Report_SymbolProblems($Priority, $Level)) {
17820 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017822 if($Priority eq "Low")
17823 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017824 $Report .= get_Report_ChangedConstants("Low", $Level);
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +040017825 if($ReportFormat eq "html")
17826 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017827 if($CheckImpl and $Level eq "Binary") {
17828 $Report .= get_Report_Impl();
17829 }
17830 }
17831 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017832 if($Priority eq "Safe")
17833 {
17834 $Report .= get_Report_ChangedConstants("Safe", $Level);
17835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017836 if($ReportFormat eq "html")
17837 {
17838 if($Report)
17839 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017840 if($JoinReport)
17841 {
17842 if($Priority eq "Safe") {
17843 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17844 }
17845 else {
17846 $Report = "<a name=\'".$Priority."_Risk_".$Level."_Problems\'></a>".$Report;
17847 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017848 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017849 else
17850 {
17851 if($Priority eq "Safe") {
17852 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17853 }
17854 else {
17855 $Report = "<a name=\'".$Priority."_Risk_Problems\'></a>".$Report;
17856 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017857 }
17858 }
17859 }
17860 return $Report;
17861}
17862
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017863sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017864{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017865 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17866 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17867 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17868 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017869 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17870 <meta name=\"keywords\" content=\"$Keywords\" />
17871 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017872 <title>
17873 $Title
17874 </title>
17875 <style type=\"text/css\">
17876 $Styles
17877 </style>
17878 <script type=\"text/javascript\" language=\"JavaScript\">
17879 <!--
17880 $Scripts
17881 -->
17882 </script>
17883 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017884}
17885
17886sub insertIDs($)
17887{
17888 my $Text = $_[0];
17889 while($Text=~/CONTENT_ID/)
17890 {
17891 if(int($Content_Counter)%2) {
17892 $ContentID -= 1;
17893 }
17894 $Text=~s/CONTENT_ID/c_$ContentID/;
17895 $ContentID += 1;
17896 $Content_Counter += 1;
17897 }
17898 return $Text;
17899}
17900
17901sub checkPreprocessedUnit($)
17902{
17903 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017904 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017905 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017906 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017907
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017908 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017909 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017910 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017911 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017912 chomp($Line);
17913 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017914 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017915 $CurHeader = path_format($1, $OSgroup);
17916 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017917 $CurClass = "";
17918
17919 if(index($CurHeader, $TMP_DIR)==0) {
17920 next;
17921 }
17922
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017923 if(substr($CurHeaderName, 0, 1) eq "<")
17924 { # <built-in>, <command-line>, etc.
17925 $CurHeaderName = "";
17926 $CurHeader = "";
17927 }
17928
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017929 if($ExtraInfo)
17930 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017931 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017932 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17933 }
17934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017935 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017936 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017937 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017938 if($CurHeaderName)
17939 {
17940 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17941 and not $Registered_Headers{$Version}{$CurHeader})
17942 { # not a target
17943 next;
17944 }
17945 if(not is_target_header($CurHeaderName, 1)
17946 and not is_target_header($CurHeaderName, 2))
17947 { # user-defined header
17948 next;
17949 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017950 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017951 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017952
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017953 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017954 {
17955 my ($Name, $Value) = ($1, $2);
17956 if(not $Constants{$Version}{$Name}{"Access"})
17957 {
17958 $Constants{$Version}{$Name}{"Access"} = "public";
17959 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017960 if($CurHeaderName) {
17961 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17962 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017963 }
17964 }
17965 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17966 $Constants{$Version}{$1}{"Access"} = "private";
17967 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017968 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017969 else
17970 {
17971 if(defined $ExtraDump)
17972 {
17973 if($Line=~/(\w+)\s*\(/)
17974 { # functions
17975 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17976 }
17977 #elsif($Line=~/(\w+)\s*;/)
17978 #{ # data
17979 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17980 #}
17981 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17982 $CurClass = $2;
17983 }
17984 }
17985 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017986 }
17987 close(PREPROC);
17988 foreach my $Constant (keys(%{$Constants{$Version}}))
17989 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017990 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17991 {
17992 delete($Constants{$Version}{$Constant});
17993 next;
17994 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017995 if(not $ExtraDump and ($Constant=~/_h\Z/i
17996 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017997 { # skip
17998 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017999 }
18000 else {
18001 delete($Constants{$Version}{$Constant}{"Access"});
18002 }
18003 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018004 if($Debug)
18005 {
18006 mkpath($DEBUG_PATH{$Version});
18007 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018009}
18010
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018011sub uncoverConstant($$)
18012{
18013 my ($LibVersion, $Constant) = @_;
18014 return "" if(not $LibVersion or not $Constant);
18015 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18016 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18017 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18018 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018019
18020 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018021 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018022 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18023 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018024 {
18025 push(@RecurConstant, $Constant);
18026 my $Uncovered = uncoverConstant($LibVersion, $Value);
18027 if($Uncovered ne "") {
18028 $Value = $Uncovered;
18029 }
18030 pop(@RecurConstant);
18031 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018032
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018033 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018034 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018035 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18036 }
18037 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18038}
18039
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018040sub simpleConstant($$)
18041{
18042 my ($LibVersion, $Value) = @_;
18043 if($Value=~/\W/)
18044 {
18045 my $Value_Copy = $Value;
18046 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18047 {
18048 my $Word = $1;
18049 if($Value!~/$Word\s*\(/)
18050 {
18051 my $Val = uncoverConstant($LibVersion, $Word);
18052 if($Val ne "")
18053 {
18054 $Value=~s/\b$Word\b/$Val/g;
18055 }
18056 }
18057 }
18058 }
18059 return $Value;
18060}
18061
18062sub computeValue($)
18063{
18064 my $Value = $_[0];
18065
18066 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18067 return $1;
18068 }
18069
18070 if($Value=~/\A[\d\-\+()]+\Z/) {
18071 return eval($Value);
18072 }
18073
18074 return $Value;
18075}
18076
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018077my %IgnoreConstant = map {$_=>1} (
18078 "VERSION",
18079 "VERSIONCODE",
18080 "VERNUM",
18081 "VERS_INFO",
18082 "PATCHLEVEL",
18083 "INSTALLPREFIX",
18084 "VBUILD",
18085 "VPATCH",
18086 "VMINOR",
18087 "BUILD_STRING",
18088 "BUILD_TIME",
18089 "PACKAGE_STRING",
18090 "PRODUCTION",
18091 "CONFIGURE_COMMAND",
18092 "INSTALLDIR",
18093 "BINDIR",
18094 "CONFIG_FILE_PATH",
18095 "DATADIR",
18096 "EXTENSION_DIR",
18097 "INCLUDE_PATH",
18098 "LIBDIR",
18099 "LOCALSTATEDIR",
18100 "SBINDIR",
18101 "SYSCONFDIR",
18102 "RELEASE",
18103 "SOURCE_ID",
18104 "SUBMINOR",
18105 "MINOR",
18106 "MINNOR",
18107 "MINORVERSION",
18108 "MAJOR",
18109 "MAJORVERSION",
18110 "MICRO",
18111 "MICROVERSION",
18112 "BINARY_AGE",
18113 "INTERFACE_AGE",
18114 "CORE_ABI",
18115 "PATCH",
18116 "COPYRIGHT",
18117 "TIMESTAMP",
18118 "REVISION",
18119 "PACKAGE_TAG",
18120 "PACKAGEDATE",
18121 "NUMVERSION",
18122 "Release",
18123 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018124);
18125
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018126sub constantFilter($$$)
18127{
18128 my ($Name, $Value, $Level) = @_;
18129
18130 if($Level eq "Binary")
18131 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018132 if($Name=~/_t\Z/)
18133 { # __malloc_ptr_t
18134 return 1;
18135 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018136 foreach (keys(%IgnoreConstant))
18137 {
18138 if($Name=~/(\A|_)$_(_|\Z)/)
18139 { # version
18140 return 1;
18141 }
18142 if(/\A[A-Z].*[a-z]\Z/)
18143 {
18144 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18145 { # version
18146 return 1;
18147 }
18148 }
18149 }
18150 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18151 { # version
18152 return 1;
18153 }
18154 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18155 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18156 return 1;
18157 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018158
18159 if($Value=~/\A["'].*['"]/i)
18160 { # string
18161 return 0;
18162 }
18163
18164 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18165 { # static int gcry_pth_init
18166 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018167 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018168 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018169 return 1;
18170 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018171 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018172 { # foo(p)
18173 return 1;
18174 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018175 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018176 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018177 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018178 return 1;
18179 }
18180 }
18181
18182 return 0;
18183}
18184
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018185sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018186{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018187 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018188 foreach my $Constant (keys(%{$Constants{1}}))
18189 {
18190 if($SkipConstants{1}{$Constant})
18191 { # skipped by the user
18192 next;
18193 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018194
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018195 if(my $Header = $Constants{1}{$Constant}{"Header"})
18196 {
18197 if(not is_target_header($Header, 1)
18198 and not is_target_header($Header, 2))
18199 { # user-defined header
18200 next;
18201 }
18202 }
18203 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018204 next;
18205 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018206
18207 my $Old_Value = uncoverConstant(1, $Constant);
18208
18209 if(constantFilter($Constant, $Old_Value, $Level))
18210 { # separate binary and source problems
18211 next;
18212 }
18213
18214 if(not defined $Constants{2}{$Constant}{"Value"})
18215 { # removed
18216 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18217 "Target"=>$Constant,
18218 "Old_Value"=>$Old_Value );
18219 next;
18220 }
18221
18222 if($Constants{2}{$Constant}{"Value"} eq "")
18223 { # empty value
18224 # TODO: implement a rule
18225 next;
18226 }
18227
18228 my $New_Value = uncoverConstant(2, $Constant);
18229
18230 my $Old_Value_Pure = $Old_Value;
18231 my $New_Value_Pure = $New_Value;
18232
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018233 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18234 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18235 $New_Value_Pure=~s/(\W)\s+/$1/g;
18236 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018237
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018238 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018239
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018240 if($New_Value_Pure ne $Old_Value_Pure)
18241 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018242 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18243 { # complex values
18244 next;
18245 }
18246 if(computeValue($Old_Value) eq computeValue($New_Value))
18247 { # expressions
18248 next;
18249 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018250 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18251 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18252 next;
18253 }
18254 if($Old_Value eq "0" and $New_Value eq "NULL")
18255 { # 0 => NULL
18256 next;
18257 }
18258 if($Old_Value eq "NULL" and $New_Value eq "0")
18259 { # NULL => 0
18260 next;
18261 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018262 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018263 "Target"=>$Constant,
18264 "Old_Value"=>$Old_Value,
18265 "New_Value"=>$New_Value );
18266 }
18267 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018268
18269 foreach my $Constant (keys(%{$Constants{2}}))
18270 {
18271 if(not defined $Constants{1}{$Constant}{"Value"})
18272 {
18273 if($SkipConstants{2}{$Constant})
18274 { # skipped by the user
18275 next;
18276 }
18277
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018278 if(my $Header = $Constants{2}{$Constant}{"Header"})
18279 {
18280 if(not is_target_header($Header, 1)
18281 and not is_target_header($Header, 2))
18282 { # user-defined header
18283 next;
18284 }
18285 }
18286 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018287 next;
18288 }
18289
18290 my $New_Value = uncoverConstant(2, $Constant);
18291 if(not defined $New_Value or $New_Value eq "") {
18292 next;
18293 }
18294
18295 if(constantFilter($Constant, $New_Value, $Level))
18296 { # separate binary and source problems
18297 next;
18298 }
18299
18300 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18301 "Target"=>$Constant,
18302 "New_Value"=>$New_Value );
18303 }
18304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018305}
18306
18307sub convert_integer($)
18308{
18309 my $Value = $_[0];
18310 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018311 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018312 return hex($Value);
18313 }
18314 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018315 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018316 return oct($Value);
18317 }
18318 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018319 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018320 return oct($Value);
18321 }
18322 else {
18323 return $Value;
18324 }
18325}
18326
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018327sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018328{
18329 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018330 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018331 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018332 {
18333 if($LibVersion==1)
18334 {
18335 printMsg("WARNING", "checking headers only");
18336 $CheckHeadersOnly = 1;
18337 }
18338 else {
18339 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18340 }
18341 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018342
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018343 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018344 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018345 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018346
18347 if($CheckUndefined)
18348 {
18349 my %UndefinedLibs = ();
18350
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018351 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18352
18353 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018354 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018355 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018356 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018357 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018358 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018359 if($Symbol_Library{$LibVersion}{$Symbol}
18360 or $DepSymbol_Library{$LibVersion}{$Symbol})
18361 { # exported by target library
18362 next;
18363 }
18364 if(index($Symbol, '@')!=-1)
18365 { # exported default symbol version (@@)
18366 $Symbol=~s/\@/\@\@/;
18367 if($Symbol_Library{$LibVersion}{$Symbol}
18368 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18369 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018370 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018371 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018372 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18373 $UndefinedLibs{$Path} = 1;
18374 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018375 }
18376 }
18377 }
18378 if($ExtraInfo)
18379 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018380 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018381 {
18382 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018383 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018384 foreach (@Paths)
18385 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018386 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018387 my ($Dir, $Name) = separate_path($_);
18388
18389 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018390 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018391 }
18392
18393 $Name = parse_libname($Name, "name", $OStarget);
18394 $Name=~s/\Alib//;
18395
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018396 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018397 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018398
18399 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18400 {
18401 $LibString = " -L".esc($Dir).$LibString;
18402 }
18403
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018404 writeFile($ExtraInfo."/libs-string", $LibString);
18405 }
18406 }
18407 }
18408
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018409 if($ExtraInfo) {
18410 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18411 }
18412
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018413 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018414 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018415 if($#LibPaths!=-1)
18416 {
18417 if(not keys(%{$Symbol_Library{$LibVersion}}))
18418 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018419 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018420 printMsg("WARNING", "checking headers only");
18421 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018422 }
18423 }
18424 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018425
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018426 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018427 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018428}
18429
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018430my %Prefix_Lib_Map=(
18431 # symbols for autodetecting library dependencies (by prefix)
18432 "pthread_" => ["libpthread"],
18433 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18434 "cairo_" => ["libcairo"],
18435 "gtk_" => ["libgtk-x11-2.0"],
18436 "atk_" => ["libatk-1.0"],
18437 "gdk_" => ["libgdk-x11-2.0"],
18438 "gl" => ["libGL"],
18439 "glu" => ["libGLU"],
18440 "popt" => ["libpopt"],
18441 "Py" => ["libpython"],
18442 "jpeg_" => ["libjpeg"],
18443 "BZ2_" => ["libbz2"],
18444 "Fc" => ["libfontconfig"],
18445 "Xft" => ["libXft"],
18446 "SSL_" => ["libssl"],
18447 "sem_" => ["libpthread"],
18448 "snd_" => ["libasound"],
18449 "art_" => ["libart_lgpl_2"],
18450 "dbus_g" => ["libdbus-glib-1"],
18451 "GOMP_" => ["libgomp"],
18452 "omp_" => ["libgomp"],
18453 "cms" => ["liblcms"]
18454);
18455
18456my %Pattern_Lib_Map=(
18457 "SL[a-z]" => ["libslang"]
18458);
18459
18460my %Symbol_Lib_Map=(
18461 # symbols for autodetecting library dependencies (by name)
18462 "pow" => "libm",
18463 "fmod" => "libm",
18464 "sin" => "libm",
18465 "floor" => "libm",
18466 "cos" => "libm",
18467 "dlopen" => "libdl",
18468 "deflate" => "libz",
18469 "inflate" => "libz",
18470 "move_panel" => "libpanel",
18471 "XOpenDisplay" => "libX11",
18472 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018473 "clock_gettime" => "librt",
18474 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018475);
18476
18477sub find_SymbolLibs($$)
18478{
18479 my ($LibVersion, $Symbol) = @_;
18480
18481 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18482 { # debug symbols
18483 return ();
18484 }
18485
18486 my %Paths = ();
18487
18488 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18489 {
18490 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18491 $Paths{$Path} = 1;
18492 }
18493 }
18494
18495 if(my $SymbolPrefix = getPrefix($Symbol))
18496 {
18497 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18498 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18499 }
18500
18501 if(not keys(%Paths))
18502 {
18503 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18504 {
18505 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18506 {
18507 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18508 $Paths{$Path} = 1;
18509 }
18510 }
18511 }
18512 }
18513
18514 if(not keys(%Paths))
18515 {
18516 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18517 {
18518 if($Symbol=~/\A$Prefix/)
18519 {
18520 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18521 {
18522 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18523 $Paths{$Path} = 1;
18524 }
18525 }
18526 }
18527 }
18528 }
18529
18530 if(not keys(%Paths))
18531 {
18532 if($SymbolPrefix)
18533 { # try to find a library by symbol prefix
18534 if($SymbolPrefix eq "inotify" and
18535 index($Symbol, "\@GLIBC")!=-1)
18536 {
18537 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18538 $Paths{$Path} = 1;
18539 }
18540 }
18541 else
18542 {
18543 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18544 $Paths{$Path} = 1;
18545 }
18546 }
18547 }
18548 }
18549
18550 if(my @Paths = keys(%Paths)) {
18551 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18552 }
18553 }
18554 return keys(%Paths);
18555}
18556
18557sub get_LibPath_Prefix($$)
18558{
18559 my ($LibVersion, $Prefix) = @_;
18560
18561 $Prefix = lc($Prefix);
18562 $Prefix=~s/[_]+\Z//g;
18563
18564 foreach ("-2", "2", "-1", "1", "")
18565 { # libgnome-2.so
18566 # libxml2.so
18567 # libdbus-1.so
18568 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18569 return $Path;
18570 }
18571 }
18572 return "";
18573}
18574
18575sub getPrefix($)
18576{
18577 my $Str = $_[0];
18578 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18579 { # XmuValidArea: Xmu
18580 return $1;
18581 }
18582 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18583 { # snfReadFont: snf
18584 return $1;
18585 }
18586 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18587 { # XRRTimes: XRR
18588 return $1;
18589 }
18590 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18591 { # H5HF_delete: H5
18592 return $1;
18593 }
18594 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18595 { # alarm_event_add: alarm_
18596 return $1;
18597 }
18598 elsif($Str=~/\A(([a-z])\2{1,})/i)
18599 { # ffopen
18600 return $1;
18601 }
18602 return "";
18603}
18604
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018605sub getSymbolSize($$)
18606{ # size from the shared library
18607 my ($Symbol, $LibVersion) = @_;
18608 return 0 if(not $Symbol);
18609 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18610 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18611 {
18612 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18613 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18614 {
18615 if($Size<0) {
18616 return -$Size;
18617 }
18618 }
18619 }
18620 return 0;
18621}
18622
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018623sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018624{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18625 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018626 my ($Name, $Type) = @_;
18627
18628 # single
18629 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018630 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018631 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018632 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018633 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018634
18635 # double
18636 if($Name=~/$DEFAULT_STD_PARMS/)
18637 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018638 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018639 {
18640 my ($ShortName, $FuncParams) = split_Signature($Name);
18641
18642 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18643 {
18644 if(index($FParam, "<")!=-1)
18645 {
18646 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18647 my $FParam_N = canonifyName($FParam, "T");
18648 if($FParam_N ne $FParam) {
18649 $Name=~s/\Q$FParam\E/$FParam_N/g;
18650 }
18651 }
18652 }
18653 }
18654 elsif($Type eq "T")
18655 {
18656 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18657
18658 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018659 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018660 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018661 my $FParam = $TParams[0];
18662 foreach my $Pos (1 .. $#TParams)
18663 {
18664 my $TParam = $TParams[$Pos];
18665 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18666 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18667 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018668 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018669 }
18670 }
18671 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018672 if($Type eq "S") {
18673 return formatName($Name, "S");
18674 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018675 return $Name;
18676}
18677
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018678sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018679{
18680 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018681 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018682 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018683 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018684 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018685 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018686 next if($tr_name{$Symbol});
18687 $Symbol=~s/[\@\$]+(.*)\Z//;
18688 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018689 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018690 elsif(index($Symbol, "?")==0)
18691 {
18692 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018693 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018694 }
18695 else
18696 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018697 $tr_name{$Symbol} = $Symbol;
18698 $mangled_name_gcc{$Symbol} = $Symbol;
18699 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018700 }
18701 }
18702 if($#MnglNames1 > -1)
18703 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018704 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018705 foreach my $MnglName (@MnglNames1)
18706 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018707 if(my $Unmangled = pop(@UnmangledNames))
18708 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018709 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018710 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18711 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18712 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018713 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018714 and $tr_name{$MnglName}=~/vtable for (.+)/)
18715 { # bind class name and v-table symbol
18716 my $ClassName = $1;
18717 $ClassVTable{$ClassName} = $MnglName;
18718 $VTableClass{$MnglName} = $ClassName;
18719 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018720 }
18721 }
18722 }
18723 if($#MnglNames2 > -1)
18724 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018725 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018726 foreach my $MnglName (@MnglNames2)
18727 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018728 if(my $Unmangled = pop(@UnmangledNames))
18729 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018730 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018731 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18732 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018733 }
18734 }
18735 return \%tr_name;
18736}
18737
18738sub link_symbol($$$)
18739{
18740 my ($Symbol, $RunWith, $Deps) = @_;
18741 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18742 return 1;
18743 }
18744 if($Deps eq "+Deps")
18745 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018746 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018747 return 1;
18748 }
18749 }
18750 return 0;
18751}
18752
18753sub link_symbol_internal($$$)
18754{
18755 my ($Symbol, $RunWith, $Where) = @_;
18756 return 0 if(not $Where or not $Symbol);
18757 if($Where->{$RunWith}{$Symbol})
18758 { # the exact match by symbol name
18759 return 1;
18760 }
18761 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18762 { # indirect symbol version, i.e.
18763 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018764 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018765 if($Where->{$RunWith}{$VSym}) {
18766 return 1;
18767 }
18768 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018769 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018770 if($Sym and $Ver)
18771 { # search for the symbol with the same version
18772 # or without version
18773 if($Where->{$RunWith}{$Sym})
18774 { # old: foo@v|foo@@v
18775 # new: foo
18776 return 1;
18777 }
18778 if($Where->{$RunWith}{$Sym."\@".$Ver})
18779 { # old: foo|foo@@v
18780 # new: foo@v
18781 return 1;
18782 }
18783 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18784 { # old: foo|foo@v
18785 # new: foo@@v
18786 return 1;
18787 }
18788 }
18789 return 0;
18790}
18791
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018792sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018793{
18794 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018795 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018796 my @Imported = ();
18797 if($OSgroup eq "macos")
18798 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018799 my $NM = get_CmdPath("nm");
18800 if(not $NM) {
18801 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018802 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018803 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018804 while(<APP>)
18805 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018806 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018807 push(@Imported, $1);
18808 }
18809 }
18810 close(APP);
18811 }
18812 elsif($OSgroup eq "windows")
18813 {
18814 my $DumpBinCmd = get_CmdPath("dumpbin");
18815 if(not $DumpBinCmd) {
18816 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18817 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018818 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018819 while(<APP>)
18820 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018821 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18822 push(@Imported, $1);
18823 }
18824 }
18825 close(APP);
18826 }
18827 else
18828 {
18829 my $ReadelfCmd = get_CmdPath("readelf");
18830 if(not $ReadelfCmd) {
18831 exitStatus("Not_Found", "can't find \"readelf\"");
18832 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018833 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018834 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018835 while(<APP>)
18836 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018837 if(defined $symtab)
18838 { # do nothing with symtab
18839 if(index($_, "'.dynsym'")!=-1)
18840 { # dynamic table
18841 $symtab = undef;
18842 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018843 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018844 elsif(index($_, "'.symtab'")!=-1)
18845 { # symbol table
18846 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018847 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018848 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018849 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018850 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18851 if($Ndx eq "UND")
18852 { # only imported symbols
18853 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018854 }
18855 }
18856 }
18857 close(APP);
18858 }
18859 return @Imported;
18860}
18861
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018862my %ELF_BIND = map {$_=>1} (
18863 "WEAK",
18864 "GLOBAL"
18865);
18866
18867my %ELF_TYPE = map {$_=>1} (
18868 "FUNC",
18869 "IFUNC",
18870 "OBJECT",
18871 "COMMON"
18872);
18873
18874my %ELF_VIS = map {$_=>1} (
18875 "DEFAULT",
18876 "PROTECTED"
18877);
18878
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018879sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018880{ # read the line of 'readelf' output corresponding to the symbol
18881 my @Info = split(/\s+/, $_[0]);
18882 # Num: Value Size Type Bind Vis Ndx Name
18883 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018884 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018885 shift(@Info); # spaces
18886 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018887
18888 if($#Info==7)
18889 { # UND SYMBOL (N)
18890 if($Info[7]=~/\(\d+\)/) {
18891 pop(@Info);
18892 }
18893 }
18894
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018895 if($#Info!=6)
18896 { # other lines
18897 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018898 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018899 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018900 return () if(not defined $ELF_BIND{$Info[3]});
18901 return () if(not defined $ELF_VIS{$Info[4]});
18902 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18903 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18904 return ();
18905 }
18906 if($OStarget eq "symbian")
18907 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18908 if(index($Info[6], "_._.absent_export_")!=-1)
18909 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18910 return ();
18911 }
18912 $Info[6]=~s/\@.+//g; # remove version
18913 }
18914 if(index($Info[2], "0x") == 0)
18915 { # size == 0x3d158
18916 $Info[2] = hex($Info[2]);
18917 }
18918 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018919}
18920
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018921sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018922{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018923 my ($LibVersion, $Name) = @_;
18924 return "" if(not $LibVersion or not $Name);
18925 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18926 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018927 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018928 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18929}
18930
18931sub get_LibPath_I($$)
18932{
18933 my ($LibVersion, $Name) = @_;
18934 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018935 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018936 if(-f $Name)
18937 { # absolute path
18938 return $Name;
18939 }
18940 else
18941 { # broken
18942 return "";
18943 }
18944 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018945 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018946 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018947 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018948 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018949 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018950 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018951 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018952 }
18953 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18954 { # ldconfig default paths
18955 return $DefaultPath;
18956 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018957 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018958 { # search in default linker directories
18959 # and then in all system paths
18960 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018961 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018962 }
18963 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018964 if(not defined $Cache{"checkSystemFiles"}) {
18965 checkSystemFiles();
18966 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018967 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18968 return $AllObjects[0];
18969 }
18970 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18971 {
18972 if($ShortName ne $Name)
18973 { # FIXME: check this case
18974 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18975 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018976 }
18977 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018978 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018979 # can't find
18980 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018981}
18982
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018983sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018984{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018985 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18986 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018987
18988 my $Real_Path = realpath($Lib_Path);
18989
18990 if(not $Real_Path)
18991 { # broken link
18992 return ();
18993 }
18994
18995 my $Lib_Name = get_filename($Real_Path);
18996
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018997 if($ExtraInfo)
18998 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018999 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019000 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019001 }
19002
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019003 if($IsNeededLib)
19004 {
19005 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19006 return ();
19007 }
19008 }
19009 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019010 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019011
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019012 if($CheckImpl)
19013 {
19014 if(not $IsNeededLib) {
19015 getImplementations($LibVersion, $Lib_Path);
19016 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019017 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019018
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019019 push(@RecurLib, $Lib_Name);
19020 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019021 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19022
19023 if(not $IsNeededLib)
19024 { # special cases: libstdc++ and libc
19025 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19026 {
19027 if($ShortName eq "libstdc++")
19028 { # libstdc++.so.6
19029 $STDCXX_TESTING = 1;
19030 }
19031 elsif($ShortName eq "libc")
19032 { # libc-2.11.3.so
19033 $GLIBC_TESTING = 1;
19034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019035 }
19036 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019037 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019038 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019039 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019040 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019041 mkpath(get_dirname($DebugPath));
19042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019043 if($OStarget eq "macos")
19044 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019045 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019046 if(not $NM) {
19047 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019048 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019049 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019050 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019051 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019052 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019053 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019054 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019055 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019056 else
19057 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019058 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019060 while(<LIB>)
19061 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019062 if($CheckUndefined)
19063 {
19064 if(not $IsNeededLib)
19065 {
19066 if(/ U _([\w\$]+)\s*\Z/)
19067 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019068 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019069 next;
19070 }
19071 }
19072 }
19073
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019074 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019075 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019076 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019077 if($IsNeededLib)
19078 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019079 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019080 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019081 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19082 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019083 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019084 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019085 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019086 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019087 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19088 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019089 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19090 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019091 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019092 setLanguage($LibVersion, "C++");
19093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019094 }
19095 if($CheckObjectsOnly
19096 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019097 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019098 }
19099 }
19100 }
19101 }
19102 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019103
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019104 if($Deps)
19105 {
19106 if($LIB_TYPE eq "dynamic")
19107 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019108
19109 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019110 if(not $OtoolCmd) {
19111 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019112 }
19113
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019114 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19115 while(<LIB>)
19116 {
19117 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19118 and $1 ne $Lib_Path) {
19119 $NeededLib{$1} = 1;
19120 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019121 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019122 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019123 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019124 }
19125 }
19126 elsif($OStarget eq "windows")
19127 { # Windows *.dll, *.lib
19128 my $DumpBinCmd = get_CmdPath("dumpbin");
19129 if(not $DumpBinCmd) {
19130 exitStatus("Not_Found", "can't find \"dumpbin\"");
19131 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019132 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019133 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019134 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019135 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019136 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019137 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019138 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019139 else
19140 { # write to pipe
19141 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019142 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019143 while(<LIB>)
19144 { # 1197 4AC 0000A620 SetThreadStackGuarantee
19145 # 1198 4AD SetThreadToken (forwarded to ...)
19146 # 3368 _o2i_ECPublicKey
19147 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*\Z/i
19148 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
19149 or /\A\s*\d+\s+_([\w\?\@]+)\s*\Z/)
19150 { # dynamic, static and forwarded symbols
19151 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019152 if($IsNeededLib)
19153 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019154 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019155 {
19156 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19157 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19158 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019159 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019160 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019161 {
19162 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19163 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019164 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19165 {
19166 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19167 setLanguage($LibVersion, "C++");
19168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019169 }
19170 if($CheckObjectsOnly
19171 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019172 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019173 }
19174 }
19175 }
19176 }
19177 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019178
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019179 if($Deps)
19180 {
19181 if($LIB_TYPE eq "dynamic")
19182 { # dependencies
19183 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19184 while(<LIB>)
19185 {
19186 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19187 and $1 ne $Lib_Path) {
19188 $NeededLib{path_format($1, $OSgroup)} = 1;
19189 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019190 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019191 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019192 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019193 }
19194 }
19195 else
19196 { # Unix; *.so, *.a
19197 # Symbian: *.dso, *.lib
19198 my $ReadelfCmd = get_CmdPath("readelf");
19199 if(not $ReadelfCmd) {
19200 exitStatus("Not_Found", "can't find \"readelf\"");
19201 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019202 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019203 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019204 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019205 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019206 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019207 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019208 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019209 else
19210 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019211 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019212 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019213 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019214 while(<LIB>)
19215 {
19216 if($LIB_TYPE eq "dynamic")
19217 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019218 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019219 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019220 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019221 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019222 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019223 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019224 # do nothing with symtab
19225 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019226 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019227 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019228 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019229 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019230 next;
19231 }
19232 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019233 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019234 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019235 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019236 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019237 if($CheckUndefined)
19238 {
19239 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019240 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019241 }
19242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019243 next;
19244 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019245 if($Bind eq "WEAK")
19246 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019247 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019248 if($Weak eq "-Weak")
19249 { # skip WEAK symbols
19250 next;
19251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019252 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019253 my $Short = $Symbol;
19254 $Short=~s/\@.+//g;
19255 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019256 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019257 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19258 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019259 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019260 if($IsNeededLib)
19261 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019262 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019263 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019264 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19265 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019266 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019267 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019268 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019269 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019270 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19271 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19272 if($Vers)
19273 {
19274 if($LIB_EXT eq "so")
19275 { # value
19276 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19277 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19278 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019279 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019280 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19281 {
19282 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19283 setLanguage($LibVersion, "C++");
19284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019285 }
19286 if($CheckObjectsOnly
19287 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019288 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019289 }
19290 }
19291 }
19292 }
19293 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019294
19295 if($Deps and $LIB_TYPE eq "dynamic")
19296 { # dynamic library specifics
19297 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19298 open(LIB, $Cmd." |");
19299
19300 while(<LIB>)
19301 {
19302 if(/NEEDED.+\[([^\[\]]+)\]/)
19303 { # dependencies:
19304 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19305 $NeededLib{$1} = 1;
19306 }
19307 }
19308
19309 close(LIB);
19310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019311 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019312 if($Vers)
19313 {
19314 if(not $IsNeededLib and $LIB_EXT eq "so")
19315 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019316 my %Found = ();
19317
19318 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019319 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019320 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019321 next if(index($Symbol,"\@")==-1);
19322 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019323 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019324 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019325 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019326 if($Symbol_SameValue ne $Symbol
19327 and index($Symbol_SameValue,"\@")==-1)
19328 {
19329 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019330 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019331 last;
19332 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019333 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019334 }
19335 }
19336
19337 # 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;
19348 }
19349 }
19350
19351 # non-default
19352 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19353 {
19354 next if(defined $Found{$Symbol});
19355 next if(index($Symbol,"\@")==-1);
19356
19357 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19358 and not $SymVer{$LibVersion}{$1})
19359 {
19360 $SymVer{$LibVersion}{$1} = $Symbol;
19361 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019362 }
19363 }
19364 }
19365 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019366 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019367 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019368 foreach my $DyLib (sort keys(%NeededLib))
19369 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019370 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19371
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019372 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19373 {
19374 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19375 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19376 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019377 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019378 }
19379 }
19380 pop(@RecurLib);
19381 return $Library_Symbol{$LibVersion};
19382}
19383
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019384sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019385{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019386 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019387 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019388 return keys(%Prefixes);
19389}
19390
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019391sub get_prefixes_I($$)
19392{
19393 foreach my $P (@{$_[0]})
19394 {
19395 my @Parts = reverse(split(/[\/\\]+/, $P));
19396 my $Name = $Parts[0];
19397 foreach (1 .. $#Parts)
19398 {
19399 $_[1]->{$Name}{$P} = 1;
19400 last if($_>4 or $Parts[$_] eq "include");
19401 $Name = $Parts[$_].$SLASH.$Name;
19402 }
19403 }
19404}
19405
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019406sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019407{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019408 $Cache{"checkSystemFiles"} = 1;
19409
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019410 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019411
19412 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019413 {
19414 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019415
19416 my @Files = cmd_find($DevelPath);
19417
19418 if(not $CheckObjectsOnly)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019419 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019420 # search for headers in /usr/lib
Andrey Ponomarenko13bb0332013-06-28 15:32:28 +040019421 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19422 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19423 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019424 }
19425
19426 # search for libraries in /usr/lib (including symbolic links)
19427 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19428 foreach my $Path (@Libs)
19429 {
19430 my $N = get_filename($Path);
19431 $SystemObjects{$N}{$Path} = 1;
19432 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019433 }
19434 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019435
19436 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019437 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019438 foreach my $DevelPath (@{$SystemPaths{"include"}})
19439 {
19440 next if(not -d $DevelPath);
19441 # search for all header files in the /usr/include
19442 # with or without extension (ncurses.h, QtCore, ...)
19443 push(@SysHeaders, cmd_find($DevelPath,"f"));
19444 foreach my $Link (cmd_find($DevelPath,"l"))
19445 { # add symbolic links
19446 if(-f $Link) {
19447 push(@SysHeaders, $Link);
19448 }
19449 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019450 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019451 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019452 }
19453}
19454
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019455sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019456{
19457 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019458 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019459 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19460 {
19461 if(not -e $Dest) {
19462 exitStatus("Access_Error", "can't access \'$Dest\'");
19463 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019464 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019465 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19466 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019467 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019468 }
19469 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019470 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019471}
19472
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019473sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019474{
19475 my ($Path, $LibVersion) = @_;
19476 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019477 my $Name = get_filename($Path);
19478 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019479 return 1;
19480 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019481 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019482 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19483 return 1;
19484 }
19485 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19486 {
19487 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19488 return 1;
19489 }
19490 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019491 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019492 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019493 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019494 return 1;
19495 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019496 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019497 return 1;
19498 }
19499 }
19500 return 0;
19501}
19502
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019503sub specificHeader($$)
19504{
19505 my ($Header, $Spec) = @_;
19506 my $Name = get_filename($Header);
19507
19508 if($Spec eq "windows")
19509 {# MS Windows
19510 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19511 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19512 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19513 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19514 my @Dirs = (
19515 "win32",
19516 "win64",
19517 "win",
19518 "windows",
19519 "msvcrt"
19520 ); # /gsf-win32/
19521 if(my $DIRs = join("|", @Dirs)) {
19522 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19523 }
19524 }
19525 elsif($Spec eq "macos")
19526 { # Mac OS
19527 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19528 }
19529
19530 return 0;
19531}
19532
19533sub skipAlienHeader($)
19534{
19535 my $Path = $_[0];
19536 my $Name = get_filename($Path);
19537 my $Dir = get_dirname($Path);
19538
19539 if($Tolerance=~/2/)
19540 { # 2 - skip internal headers
19541 my @Terms = (
19542 "p",
19543 "priv",
19544 "int",
19545 "impl",
19546 "implementation",
19547 "internal",
19548 "private",
19549 "old",
19550 "compat",
19551 "debug",
19552 "test",
19553 "gen"
19554 );
19555
19556 my @Dirs = (
19557 "private",
19558 "priv",
19559 "port",
19560 "impl",
19561 "internal",
19562 "detail",
19563 "details",
19564 "old",
19565 "compat",
19566 "debug",
19567 "config",
19568 "compiler",
19569 "platform",
19570 "test"
19571 );
19572
19573 if(my $TERMs = join("|", @Terms)) {
19574 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19575 }
19576 if(my $DIRs = join("|", @Dirs)) {
19577 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19578 }
19579
19580 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19581 }
19582
19583 if($Tolerance=~/1/)
19584 { # 1 - skip non-Linux headers
19585 if($OSgroup ne "windows")
19586 {
19587 if(specificHeader($Path, "windows")) {
19588 return 1;
19589 }
19590 }
19591 if($OSgroup ne "macos")
19592 {
19593 if(specificHeader($Path, "macos")) {
19594 return 1;
19595 }
19596 }
19597 }
19598
19599 # valid
19600 return 0;
19601}
19602
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019603sub skipHeader($$)
19604{
19605 my ($Path, $LibVersion) = @_;
19606 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019607 if(defined $Cache{"skipHeader"}{$Path}) {
19608 return $Cache{"skipHeader"}{$Path};
19609 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019610 if(defined $Tolerance and $Tolerance=~/1|2/)
19611 { # --tolerant
19612 if(skipAlienHeader($Path)) {
19613 return ($Cache{"skipHeader"}{$Path} = 1);
19614 }
19615 }
19616 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19617 return 0;
19618 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019619 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19620}
19621
19622sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019623{ # returns:
19624 # 1 - if header should NOT be included and checked
19625 # 2 - if header should NOT be included, but should be checked
19626 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019627 my $Name = get_filename($Path);
19628 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019629 return $Kind;
19630 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019631 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19632 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019633 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019634 if(index($Path, $D)!=-1)
19635 {
19636 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19637 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19638 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019639 }
19640 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019641 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19642 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019643 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019644 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19645 {
19646 if($Name=~/$P/) {
19647 return $Kind;
19648 }
19649 if($P=~/[\/\\]/ and $Path=~/$P/) {
19650 return $Kind;
19651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019652 }
19653 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019654
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019655 return 0;
19656}
19657
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019658sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019659{
19660 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019661 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019662 { # system directory
19663 return;
19664 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019665 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019666 { # already registered
19667 return;
19668 }
19669 foreach my $Path (find_libs($Dir,"",1))
19670 {
19671 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019672 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019673 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019674 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019675 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19676}
19677
19678sub registerObject($$)
19679{
19680 my ($Path, $LibVersion) = @_;
19681 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019682 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019683 if($OSgroup=~/linux|bsd/i)
19684 {
19685 if(my $SONAME = getSONAME($Path)) {
19686 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19687 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019688 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019689 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19690 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019691 }
19692}
19693
19694sub getSONAME($)
19695{
19696 my $Path = $_[0];
19697 return if(not $Path);
19698 if(defined $Cache{"getSONAME"}{$Path}) {
19699 return $Cache{"getSONAME"}{$Path};
19700 }
19701 my $ObjdumpCmd = get_CmdPath("objdump");
19702 if(not $ObjdumpCmd) {
19703 exitStatus("Not_Found", "can't find \"objdump\"");
19704 }
19705 my $SonameCmd = "$ObjdumpCmd -x $Path 2>$TMP_DIR/null";
19706 if($OSgroup eq "windows") {
19707 $SonameCmd .= " | find \"SONAME\"";
19708 }
19709 else {
19710 $SonameCmd .= " | grep SONAME";
19711 }
19712 if(my $SonameInfo = `$SonameCmd`) {
19713 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19714 return ($Cache{"getSONAME"}{$Path} = $1);
19715 }
19716 }
19717 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019718}
19719
19720sub getSOPaths_Dest($$)
19721{
19722 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019723 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019724 return ();
19725 }
19726 if(-f $Dest)
19727 {
19728 if(not parse_libname($Dest, "name", $OStarget)) {
19729 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19730 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019731 registerObject($Dest, $LibVersion);
19732 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019733 return ($Dest);
19734 }
19735 elsif(-d $Dest)
19736 {
19737 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019738 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019739 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019740 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19741 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019742 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019743 { # all files and symlinks that match the name of a library
19744 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19745 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019746 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019747 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019748 }
19749 }
19750 }
19751 else
19752 { # search for all files and symlinks
19753 foreach my $Path (find_libs($Dest,"",""))
19754 {
19755 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019756 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019757 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019758 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019759 }
19760 if($OSgroup eq "macos")
19761 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019762 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019763 {
19764 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019765 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019766 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019767 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19768 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019769 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019770 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019771 }
19772 }
19773 }
19774 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019775 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019776 }
19777 else {
19778 return ();
19779 }
19780}
19781
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019782sub isCyclical($$)
19783{
19784 my ($Stack, $Value) = @_;
19785 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019786}
19787
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019788sub detectWordSize()
19789{
19790 return "" if(not $GCC_PATH);
19791 if($Cache{"detectWordSize"}) {
19792 return $Cache{"detectWordSize"};
19793 }
19794 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019795 my $Defines = `$GCC_PATH -E -dD \"$TMP_DIR/empty.h\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019796 unlink("$TMP_DIR/empty.h");
19797 my $WSize = 0;
19798 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019799 { # GCC 4
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019800 $WSize = $1;
19801 }
19802 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019803 { # GCC 3
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019804 my $PTRDIFF = $1;
19805 if($PTRDIFF=~/long/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019806 $WSize = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019807 }
19808 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019809 $WSize = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019810 }
19811 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019812 if(not $WSize) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019813 exitStatus("Error", "can't check WORD size");
19814 }
19815 return ($Cache{"detectWordSize"} = $WSize);
19816}
19817
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019818sub getWordSize($) {
19819 return $WORD_SIZE{$_[0]};
19820}
19821
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019822sub majorVersion($)
19823{
19824 my $V = $_[0];
19825 return 0 if(not $V);
19826 my @VParts = split(/\./, $V);
19827 return $VParts[0];
19828}
19829
19830sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019831{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019832 my ($V1, $V2) = @_;
19833 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019834 my @V1Parts = split(/\./, $V1);
19835 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019836 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19837 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019838 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19839 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19840 }
19841 return -1 if($#V1Parts < $#V2Parts);
19842 return 1 if($#V1Parts > $#V2Parts);
19843 return 0;
19844}
19845
19846sub read_ABI_Dump($$)
19847{
19848 my ($LibVersion, $Path) = @_;
19849 return if(not $LibVersion or not -e $Path);
19850 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019851 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019852 { # input *.abi
19853 $FilePath = $Path;
19854 }
19855 else
19856 { # input *.abi.tar.gz
19857 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019858 if(not isDump_U($FilePath)) {
19859 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019861 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019862
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019863 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019864
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019865 my $Line = readLineNum($FilePath, 0);
19866 if($Line=~/xml/)
19867 { # XML format
19868 loadModule("XmlDump");
19869 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019870 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019871 else
19872 { # Perl Data::Dumper format (default)
19873 open(DUMP, $FilePath);
19874 local $/ = undef;
19875 my $Content = <DUMP>;
19876 close(DUMP);
19877
19878 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19879 { # remove temp file
19880 unlink($FilePath);
19881 }
19882 if($Content!~/};\s*\Z/) {
19883 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19884 }
19885 $ABI = eval($Content);
19886 if(not $ABI) {
19887 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19888 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019889 }
19890 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019891 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019892 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019893 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019894 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019895 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019896 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019897 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019898
19899 if($ABI->{"ABI_DUMP_VERSION"})
19900 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019901 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019902 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019903 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019904 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019905 }
19906 else
19907 { # support for old ABI dumps
19908 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019909 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019910 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019911 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019912 }
19913 if(majorVersion($DVersion)<2)
19914 { # support for old ABI dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019915 if($UseOldDumps)
19916 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019917 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
19918 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019919 }
19920 }
19921 else
19922 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019923 my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019924 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019925 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019926 }
19927 exitStatus("Dump_Version", $Msg);
19928 }
19929 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019930
19931 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19932 { # DWARF ABI Dump
19933 $UseConv_Real{$LibVersion}{"P"} = 1;
19934 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19935
19936 $UsedDump{$LibVersion}{"DWARF"} = 1;
19937
19938 $TargetComponent = "module";
19939 }
19940
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019941 if(not checkDump($LibVersion, "2.11"))
19942 { # old ABI dumps
19943 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019944 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019945 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019946 { # ABI dump created with --binary option
19947 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19948 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019949 else
19950 { # default
19951 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19952 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019953
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019954 if(defined $ABI->{"Mode"}
19955 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019956 { # --ext option
19957 $ExtendedCheck = 1;
19958 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019959 if($ABI->{"Extra"}) {
19960 $ExtraDump = 1;
19961 }
19962
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019963 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019964 {
19965 $UsedDump{$LibVersion}{"L"} = $Lang;
19966 setLanguage($LibVersion, $Lang);
19967 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019968 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019969 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019970 }
19971 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019972 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019973 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019974 if(not $TInfo)
19975 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019976 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019977 }
19978 my %Tid_TDid = ();
19979 foreach my $TDid (keys(%{$TInfo}))
19980 {
19981 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19982 {
19983 $MAX_ID = $Tid if($Tid>$MAX_ID);
19984 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019985 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019986 }
19987 }
19988 my %NewID = ();
19989 foreach my $Tid (keys(%Tid_TDid))
19990 {
19991 my @TDids = keys(%{$Tid_TDid{$Tid}});
19992 if($#TDids>=1)
19993 {
19994 foreach my $TDid (@TDids)
19995 {
19996 if($TDid) {
19997 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19998 }
19999 else
20000 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020001 my $ID = ++$MAX_ID;
20002
20003 $NewID{$TDid}{$Tid} = $ID;
20004 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20005 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020006 }
20007 }
20008 }
20009 else
20010 {
20011 my $TDid = $TDids[0];
20012 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20013 }
20014 }
20015 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20016 {
20017 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20018 if(defined $Info{"BaseType"})
20019 {
20020 my $Bid = $Info{"BaseType"}{"Tid"};
20021 my $BDid = $Info{"BaseType"}{"TDid"};
20022 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020023 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020024 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20025 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20026 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020027 }
20028 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20029 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020030 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020031 read_Machine_DumpInfo($ABI, $LibVersion);
20032 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020033 if(not $SymbolInfo{$LibVersion})
20034 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020035 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020036 }
20037 if(not keys(%{$SymbolInfo{$LibVersion}}))
20038 { # validation of old-version dumps
20039 if(not $ExtendedCheck) {
20040 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20041 }
20042 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020043 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020044 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020045 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020046 else
20047 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020048 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020049 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020050 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020051 }
20052 if(not $DepSymbols)
20053 { # Cannot reconstruct DepSymbols. This may result in false
20054 # positives if the old dump is for library 2. Not a problem if
20055 # old dumps are only from old libraries.
20056 $DepSymbols = {};
20057 }
20058 foreach my $Symbol (keys(%{$DepSymbols})) {
20059 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20060 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020061 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020062 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
20063 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20064 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020065 if(not $SkipTypes{$LibVersion})
20066 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020067 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020068 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020069 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020070 if(not $SkipSymbols{$LibVersion})
20071 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020072 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020073 }
20074 if(not $SkipSymbols{$LibVersion})
20075 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020076 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020077 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020078 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
20079 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20080 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020081 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020082 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020083 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020084 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020085 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020086 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020087 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020088 if(not checkDump($LibVersion, "2.10.1")
20089 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020090 { # support for old ABI dumps: added target headers
20091 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020092 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020093 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020094 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020095 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020096 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020097 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020098 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020099 if(defined $ABI->{"GccConstants"})
20100 { # 3.0
20101 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20102 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20103 }
20104 }
20105
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020106 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020107 if(not $NestedNameSpaces{$LibVersion})
20108 { # support for old dumps
20109 # Cannot reconstruct NameSpaces. This may affect design
20110 # of the compatibility report.
20111 $NestedNameSpaces{$LibVersion} = {};
20112 }
20113 # target system type
20114 # needed to adopt HTML report
20115 if(not $DumpSystem)
20116 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020117 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020118 }
20119 # recreate environment
20120 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20121 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020122 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020123 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020124 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20125 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020126 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020127 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020128 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020129 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20130 {
20131 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20132 setLanguage($LibVersion, "C++");
20133 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020134 }
20135 }
20136 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020137 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20138 {
20139 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20140 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20141 }
20142 }
20143
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020144 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020145 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020146 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020147 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020148 {
20149 if(not $Symbol_Library{$LibVersion}{$MnglName}
20150 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20151 push(@VFunc, $MnglName);
20152 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020153 }
20154 }
20155 translateSymbols(@VFunc, $LibVersion);
20156 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020157 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20158
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020159 if(not checkDump($LibVersion, "3.0"))
20160 { # support for old ABI dumps
20161 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20162 {
20163 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20164 {
20165 if(ref($BaseType) eq "HASH") {
20166 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20167 }
20168 }
20169 }
20170 }
20171
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020172 if(not checkDump($LibVersion, "3.2"))
20173 { # support for old ABI dumps
20174 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20175 {
20176 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20177 {
20178 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20179 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20180 }
20181 }
20182 }
20183
20184 # repair target headers list
20185 delete($TargetHeaders{$LibVersion});
20186 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020187 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20188 }
20189 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20190 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020191 }
20192
20193 # non-target constants from anon enums
20194 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20195 {
20196 if(not $ExtraDump
20197 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20198 {
20199 delete($Constants{$LibVersion}{$Name});
20200 }
20201 }
20202 }
20203
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020204 if(not checkDump($LibVersion, "2.20"))
20205 { # support for old ABI dumps
20206 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20207 {
20208 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20209
20210 if($TType=~/Struct|Union|Enum|Typedef/)
20211 { # repair complex types first
20212 next;
20213 }
20214
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020215 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020216 {
20217 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20218 if($BType=~/Struct|Union|Enum/i)
20219 {
20220 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20221 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20222 }
20223 }
20224 }
20225 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20226 {
20227 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20228 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20229 if($TType=~/Struct|Union|Enum/) {
20230 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20231 }
20232 }
20233 }
20234
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020235 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020236 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020237 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20238 { # support for old ABI dumps < 2.0 (ACC 1.22)
20239 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20240 {
20241 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20242 {
20243 if($Access ne "public") {
20244 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20245 }
20246 }
20247 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20248 }
20249 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20250 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020251 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20252 { # support for old ABI dumps
20253 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20254 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020255 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20256 { # DWARF ABI Dumps
20257 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20258 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020259 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20260 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20261 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020262 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20263 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020264 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020265 foreach (keys(%{$TInfo{"Base"}})) {
20266 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020267 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020268 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020269 if($TInfo{"Type"} eq "MethodPtr")
20270 {
20271 if(defined $TInfo{"Param"})
20272 { # support for old ABI dumps <= 1.17
20273 if(not defined $TInfo{"Param"}{"0"})
20274 {
20275 my $Max = keys(%{$TInfo{"Param"}});
20276 foreach my $Pos (1 .. $Max) {
20277 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20278 }
20279 delete($TInfo{"Param"}{$Max});
20280 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20281 }
20282 }
20283 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020284 if($TInfo{"BaseType"} eq $TypeId)
20285 { # fix ABI dump
20286 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20287 }
20288 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020289 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020290 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020291 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020292 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20293 if(not $BName)
20294 { # broken type
20295 next;
20296 }
20297 if($TInfo{"Name"} eq $BName)
20298 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020299 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020300 next;
20301 }
20302 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20303 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020304 }
20305 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020306 }
20307 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20308 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020309 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020310 }
20311 }
20312
20313 if(not checkDump($LibVersion, "2.15"))
20314 { # support for old ABI dumps
20315 my %Dups = ();
20316 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20317 {
20318 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020319 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020320 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20321 { # remove template decls
20322 delete($SymbolInfo{$LibVersion}{$InfoId});
20323 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020325 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020326 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20327 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020328 { # templates
20329 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020330 }
20331 }
20332 }
20333
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020334 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20335 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020336 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20337 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20338 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20339 { # support for old ABI dumps (< 3.1)
20340 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20341 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20342 { # add "this" first parameter
20343 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20344 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20345
20346 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20347 {
20348 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20349 foreach my $Pos (reverse(0 .. $#Pos)) {
20350 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20351 }
20352 }
20353 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20354 }
20355 }
20356
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020357 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20358 { # ABI dumps have no mangled names for C-functions
20359 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20360 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020361 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20362 { # support for old ABI dumps
20363 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20364 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020365 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20366 { # DWARF ABI Dumps
20367 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20368 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020369 }
20370
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020371 $Descriptor{$LibVersion}{"Dump"} = 1;
20372}
20373
20374sub read_Machine_DumpInfo($$)
20375{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020376 my ($ABI, $LibVersion) = @_;
20377 if($ABI->{"Arch"}) {
20378 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020379 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020380 if($ABI->{"WordSize"}) {
20381 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020382 }
20383 else
20384 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020385 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020386 }
20387 if(not $WORD_SIZE{$LibVersion})
20388 { # support for old dumps (<1.23)
20389 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20390 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020391 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020392 }
20393 else
20394 {
20395 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020396 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020397 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020398 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20399 { # any "pointer"-type
20400 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020401 last;
20402 }
20403 }
20404 if($PSize)
20405 { # a pointer type size
20406 $WORD_SIZE{$LibVersion} = $PSize;
20407 }
20408 else {
20409 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20410 }
20411 }
20412 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020413 if($ABI->{"GccVersion"}) {
20414 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020415 }
20416}
20417
20418sub read_Libs_DumpInfo($$)
20419{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020420 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020421 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20422 if(not $Library_Symbol{$LibVersion})
20423 { # support for old dumps
20424 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20425 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020426 if(keys(%{$Library_Symbol{$LibVersion}})
20427 and not $DumpAPI) {
20428 $Descriptor{$LibVersion}{"Libs"} = "OK";
20429 }
20430}
20431
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020432sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020433{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020434 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020435
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020436 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020437 and not $DumpAPI) {
20438 $Descriptor{$LibVersion}{"Headers"} = "OK";
20439 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020440 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020441 { # headers info is stored in the old dumps in the different way
20442 if($UseOldDumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020443 and my $Name = $ABI->{"Headers"}{$Identity}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020444 { # support for old dumps: headers info corrected in 1.22
20445 $Identity = $Name;
20446 }
20447 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020448 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020449 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020450
20451 if(keys(%{$ABI->{"Sources"}})
20452 and not $DumpAPI) {
20453 $Descriptor{$LibVersion}{"Sources"} = "OK";
20454 }
20455 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
20456 { # headers info is stored in the old dumps in the different way
20457 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20458 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20459 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020460}
20461
20462sub find_libs($$$)
20463{
20464 my ($Path, $Type, $MaxDepth) = @_;
20465 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020466 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020467}
20468
20469sub createDescriptor($$)
20470{
20471 my ($LibVersion, $Path) = @_;
20472 if(not $LibVersion or not $Path
20473 or not -e $Path) {
20474 return "";
20475 }
20476 if(-d $Path)
20477 { # directory with headers files and shared objects
20478 return "
20479 <version>
20480 ".$TargetVersion{$LibVersion}."
20481 </version>
20482
20483 <headers>
20484 $Path
20485 </headers>
20486
20487 <libs>
20488 $Path
20489 </libs>";
20490 }
20491 else
20492 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020493 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020494 { # standard XML-descriptor
20495 return readFile($Path);
20496 }
20497 elsif(is_header($Path, 2, $LibVersion))
20498 { # header file
20499 return "
20500 <version>
20501 ".$TargetVersion{$LibVersion}."
20502 </version>
20503
20504 <headers>
20505 $Path
20506 </headers>
20507
20508 <libs>
20509 none
20510 </libs>";
20511 }
20512 elsif(parse_libname($Path, "name", $OStarget))
20513 { # shared object
20514 return "
20515 <version>
20516 ".$TargetVersion{$LibVersion}."
20517 </version>
20518
20519 <headers>
20520 none
20521 </headers>
20522
20523 <libs>
20524 $Path
20525 </libs>";
20526 }
20527 else
20528 { # standard XML-descriptor
20529 return readFile($Path);
20530 }
20531 }
20532}
20533
20534sub detect_lib_default_paths()
20535{
20536 my %LPaths = ();
20537 if($OSgroup eq "bsd")
20538 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020539 if(my $LdConfig = get_CmdPath("ldconfig"))
20540 {
20541 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20542 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020543 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20544 {
20545 my $Name = "lib".$1;
20546 if(not defined $LPaths{$Name}) {
20547 $LPaths{$Name} = $2;
20548 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020549 }
20550 }
20551 }
20552 else {
20553 printMsg("WARNING", "can't find ldconfig");
20554 }
20555 }
20556 else
20557 {
20558 if(my $LdConfig = get_CmdPath("ldconfig"))
20559 {
20560 if($SystemRoot and $OSgroup eq "linux")
20561 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20562 if(-e $SystemRoot."/etc/ld.so.conf") {
20563 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20564 }
20565 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020566 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20567 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020568 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20569 {
20570 my ($Name, $Path) = ($1, $2);
20571 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020572 if(not defined $LPaths{$Name})
20573 { # get first element from the list of available paths
20574
20575 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20576 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20577 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20578
20579 $LPaths{$Name} = $Path;
20580 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020581 }
20582 }
20583 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020584 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020585 printMsg("WARNING", "can't find ldconfig");
20586 }
20587 }
20588 return \%LPaths;
20589}
20590
20591sub detect_bin_default_paths()
20592{
20593 my $EnvPaths = $ENV{"PATH"};
20594 if($OSgroup eq "beos") {
20595 $EnvPaths.=":".$ENV{"BETOOLS"};
20596 }
20597 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020598 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020599 {
20600 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020601 next if(not $Path);
20602 if($SystemRoot
20603 and $Path=~/\A\Q$SystemRoot\E\//)
20604 { # do NOT use binaries from target system
20605 next;
20606 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020607 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020608 }
20609}
20610
20611sub detect_inc_default_paths()
20612{
20613 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020614 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020615 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020616 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020617 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020618 next if(index($Line, "/cc1plus ")!=-1);
20619
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020620 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20621 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020622 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020623 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020624 if(index($Path, "c++")!=-1
20625 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020626 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020627 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020628 if(not defined $MAIN_CPP_DIR
20629 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20630 $MAIN_CPP_DIR = $Path;
20631 }
20632 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020633 elsif(index($Path, "gcc")!=-1) {
20634 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020635 }
20636 else
20637 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020638 if($Path=~/local[\/\\]+include/)
20639 { # local paths
20640 next;
20641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020642 if($SystemRoot
20643 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20644 { # The GCC include path for user headers is not a part of the system root
20645 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20646 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20647 next;
20648 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020649 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020650 }
20651 }
20652 }
20653 unlink("$TMP_DIR/empty.h");
20654 return %DPaths;
20655}
20656
20657sub detect_default_paths($)
20658{
20659 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20660 my $Search = $_[0];
20661 if($Search!~/inc/) {
20662 $HSearch = 0;
20663 }
20664 if($Search!~/lib/) {
20665 $LSearch = 0;
20666 }
20667 if($Search!~/bin/) {
20668 $BSearch = 0;
20669 }
20670 if($Search!~/gcc/) {
20671 $GSearch = 0;
20672 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020673 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020674 { # <search_headers> section of the XML descriptor
20675 # do NOT search for systems headers
20676 $HSearch = 0;
20677 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020678 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020679 { # <search_headers> section of the XML descriptor
20680 # do NOT search for systems headers
20681 $LSearch = 0;
20682 }
20683 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20684 { # additional search paths
20685 next if($Type eq "include" and not $HSearch);
20686 next if($Type eq "lib" and not $LSearch);
20687 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020688 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020689 }
20690 if($OSgroup ne "windows")
20691 { # unix-like
20692 foreach my $Type ("include", "lib", "bin")
20693 { # automatic detection of system "devel" directories
20694 next if($Type eq "include" and not $HSearch);
20695 next if($Type eq "lib" and not $LSearch);
20696 next if($Type eq "bin" and not $BSearch);
20697 my ($UsrDir, $RootDir) = ("/usr", "/");
20698 if($SystemRoot and $Type ne "bin")
20699 { # 1. search for target headers and libraries
20700 # 2. use host commands: ldconfig, readelf, etc.
20701 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20702 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020703 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020704 if(-d $RootDir."/".$Type)
20705 { # if "/lib" is symbolic link
20706 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020707 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020708 }
20709 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020710 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020711 }
20712 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020713 if(-d $UsrDir)
20714 {
20715 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020716 if(-d $UsrDir."/".$Type)
20717 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020718 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020719 }
20720 }
20721 }
20722 }
20723 if($BSearch)
20724 {
20725 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020726 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020727 }
20728 # check environment variables
20729 if($OSgroup eq "beos")
20730 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020731 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020732 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020733 if($_ eq ".") {
20734 next;
20735 }
20736 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20737 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20738 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020739 }
20740 }
20741 if($HSearch)
20742 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020743 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20744 split(/:|;/, $ENV{"BEINCLUDES"})
20745 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020746 }
20747 if($LSearch)
20748 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020749 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20750 split(/:|;/, $ENV{"BELIBRARIES"}),
20751 split(/:|;/, $ENV{"LIBRARY_PATH"})
20752 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020753 }
20754 }
20755 if($LSearch)
20756 { # using linker to get system paths
20757 if(my $LPaths = detect_lib_default_paths())
20758 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020759 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020760 foreach my $Name (keys(%{$LPaths}))
20761 {
20762 if($SystemRoot
20763 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20764 { # wrong ldconfig configuration
20765 # check your <sysroot>/etc/ld.so.conf
20766 next;
20767 }
20768 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020769 if(my $Dir = get_dirname($LPaths->{$Name})) {
20770 $Dirs{$Dir} = 1;
20771 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020772 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020773 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020774 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020775 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020776 }
20777 if($BSearch)
20778 {
20779 if($CrossGcc)
20780 { # --cross-gcc=arm-linux-gcc
20781 if(-e $CrossGcc)
20782 { # absolute or relative path
20783 $GCC_PATH = get_abs_path($CrossGcc);
20784 }
20785 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20786 { # command name
20787 $GCC_PATH = $CrossGcc;
20788 }
20789 else {
20790 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20791 }
20792 if($GCC_PATH=~/\s/) {
20793 $GCC_PATH = "\"".$GCC_PATH."\"";
20794 }
20795 }
20796 }
20797 if($GSearch)
20798 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020799 if(not $CrossGcc)
20800 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020801 $GCC_PATH = get_CmdPath("gcc");
20802 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020803 if(not $GCC_PATH)
20804 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020805 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020806 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020807 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020808 { # select the latest version
20809 @GCCs = sort {$b cmp $a} @GCCs;
20810 if(check_gcc($GCCs[0], "3"))
20811 {
20812 $GCC_PATH = $GCCs[0];
20813 last;
20814 }
20815 }
20816 }
20817 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020818 if(not $GCC_PATH) {
20819 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20820 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020821
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020822 if(not $CheckObjectsOnly_Opt)
20823 {
20824 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
20825 {
20826 my $GccTarget = get_dumpmachine($GCC_PATH);
20827 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget)");
20828 if($GccTarget=~/symbian/)
20829 {
20830 $OStarget = "symbian";
20831 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20832 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020833
20834 # check GCC version
20835 if($GCC_Ver=~/\A4\.8(|\.0|\.1)\Z/)
20836 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
20837 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20838 $EMERGENCY_MODE_48 = 1;
20839 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020840 }
20841 else {
20842 exitStatus("Error", "something is going wrong with the GCC compiler");
20843 }
20844 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020845 if($HSearch)
20846 {
20847 if(not $NoStdInc)
20848 { # do NOT search in GCC standard paths
20849 my %DPaths = detect_inc_default_paths();
20850 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20851 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20852 @DefaultIncPaths = @{$DPaths{"Inc"}};
20853 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020854 }
20855 }
20856 }
20857 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020858 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020859 my $IncPath = "/usr/include";
20860 if($SystemRoot) {
20861 $IncPath = $SystemRoot.$IncPath;
20862 }
20863 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020864 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020865 }
20866 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020867
20868 if($ExtraInfo)
20869 {
20870 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20871 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020873}
20874
20875sub getLIB_EXT($)
20876{
20877 my $Target = $_[0];
20878 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20879 return $Ext;
20880 }
20881 return $OS_LibExt{$LIB_TYPE}{"default"};
20882}
20883
20884sub getAR_EXT($)
20885{
20886 my $Target = $_[0];
20887 if(my $Ext = $OS_Archive{$Target}) {
20888 return $Ext;
20889 }
20890 return $OS_Archive{"default"};
20891}
20892
20893sub get_dumpversion($)
20894{
20895 my $Cmd = $_[0];
20896 return "" if(not $Cmd);
20897 if($Cache{"get_dumpversion"}{$Cmd}) {
20898 return $Cache{"get_dumpversion"}{$Cmd};
20899 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020900 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020901 chomp($V);
20902 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20903}
20904
20905sub get_dumpmachine($)
20906{
20907 my $Cmd = $_[0];
20908 return "" if(not $Cmd);
20909 if($Cache{"get_dumpmachine"}{$Cmd}) {
20910 return $Cache{"get_dumpmachine"}{$Cmd};
20911 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020912 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020913 chomp($Machine);
20914 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20915}
20916
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020917sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020918{
20919 my $Cmd = $_[0];
20920 return "" if(not $Cmd);
20921 my @Options = (
20922 "--version",
20923 "-help"
20924 );
20925 foreach my $Opt (@Options)
20926 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020927 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020928 if($Info) {
20929 return 1;
20930 }
20931 }
20932 return 0;
20933}
20934
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020935sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020936{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020937 my ($Cmd, $ReqVer) = @_;
20938 return 0 if(not $Cmd or not $ReqVer);
20939 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20940 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020941 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020942 if(my $GccVer = get_dumpversion($Cmd))
20943 {
20944 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20945 if(cmpVersions($GccVer, $ReqVer)>=0) {
20946 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20947 }
20948 }
20949 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020950}
20951
20952sub get_depth($)
20953{
20954 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020955 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020956 }
20957 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20958}
20959
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020960sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020961{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020962 return if($Cache{"registerGccHeaders"}); # this function should be called once
20963
20964 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020965 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020966 my @Headers = cmd_find($Path,"f");
20967 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20968 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020969 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020970 my $FileName = get_filename($HPath);
20971 if(not defined $DefaultGccHeader{$FileName})
20972 { # skip duplicated
20973 $DefaultGccHeader{$FileName} = $HPath;
20974 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020975 }
20976 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020977 $Cache{"registerGccHeaders"} = 1;
20978}
20979
20980sub registerCppHeaders()
20981{
20982 return if($Cache{"registerCppHeaders"}); # this function should be called once
20983
20984 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020985 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020986 my @Headers = cmd_find($CppDir,"f");
20987 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20988 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020989 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020990 my $FileName = get_filename($Path);
20991 if(not defined $DefaultCppHeader{$FileName})
20992 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020993 $DefaultCppHeader{$FileName} = $Path;
20994 }
20995 }
20996 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020997 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020998}
20999
21000sub parse_libname($$$)
21001{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021002 return "" if(not $_[0]);
21003 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21004 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021005 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021006 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21007}
21008
21009sub parse_libname_I($$$)
21010{
21011 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021012
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021013 if($Target eq "symbian") {
21014 return parse_libname_symbian($Name, $Type);
21015 }
21016 elsif($Target eq "windows") {
21017 return parse_libname_windows($Name, $Type);
21018 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021019
21020 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021021 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021022 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021023 { # libSDL-1.2.so.0.7.1
21024 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021025 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021026 if($Type eq "name")
21027 { # libSDL-1.2
21028 # libwbxml2
21029 return $2;
21030 }
21031 elsif($Type eq "name+ext")
21032 { # libSDL-1.2.so
21033 # libwbxml2.so
21034 return $1;
21035 }
21036 elsif($Type eq "version")
21037 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021038 if(defined $7
21039 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021040 { # 0.7.1
21041 return $7;
21042 }
21043 else
21044 { # libc-2.5.so (=>2.5 version)
21045 my $MV = $5;
21046 $MV=~s/\A[\-\_]+//g;
21047 return $MV;
21048 }
21049 }
21050 elsif($Type eq "short")
21051 { # libSDL
21052 # libwbxml2
21053 return $3;
21054 }
21055 elsif($Type eq "shortest")
21056 { # SDL
21057 # wbxml
21058 return shortest_name($3);
21059 }
21060 }
21061 return "";# error
21062}
21063
21064sub parse_libname_symbian($$)
21065{
21066 my ($Name, $Type) = @_;
21067 my $Ext = getLIB_EXT("symbian");
21068 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21069 { # libpthread{00010001}.dso
21070 if($Type eq "name")
21071 { # libpthread{00010001}
21072 return $2;
21073 }
21074 elsif($Type eq "name+ext")
21075 { # libpthread{00010001}.dso
21076 return $1;
21077 }
21078 elsif($Type eq "version")
21079 { # 00010001
21080 my $V = $4;
21081 $V=~s/\{(.+)\}/$1/;
21082 return $V;
21083 }
21084 elsif($Type eq "short")
21085 { # libpthread
21086 return $3;
21087 }
21088 elsif($Type eq "shortest")
21089 { # pthread
21090 return shortest_name($3);
21091 }
21092 }
21093 return "";# error
21094}
21095
21096sub parse_libname_windows($$)
21097{
21098 my ($Name, $Type) = @_;
21099 my $Ext = getLIB_EXT("windows");
21100 if($Name=~/((.+?)\.$Ext)\Z/)
21101 { # netapi32.dll
21102 if($Type eq "name")
21103 { # netapi32
21104 return $2;
21105 }
21106 elsif($Type eq "name+ext")
21107 { # netapi32.dll
21108 return $1;
21109 }
21110 elsif($Type eq "version")
21111 { # DLL version embedded
21112 # at binary-level
21113 return "";
21114 }
21115 elsif($Type eq "short")
21116 { # netapi32
21117 return $2;
21118 }
21119 elsif($Type eq "shortest")
21120 { # netapi
21121 return shortest_name($2);
21122 }
21123 }
21124 return "";# error
21125}
21126
21127sub shortest_name($)
21128{
21129 my $Name = $_[0];
21130 # remove prefix
21131 $Name=~s/\A(lib|open)//;
21132 # remove suffix
21133 $Name=~s/[\W\d_]+\Z//i;
21134 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21135 return $Name;
21136}
21137
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021138sub createSymbolsList($$$$$)
21139{
21140 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
21141 read_ABI_Dump(1, $DPath);
21142 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021143 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021144 }
21145 my %SymbolHeaderLib = ();
21146 my $Total = 0;
21147 # Get List
21148 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21149 {
21150 if(not link_symbol($Symbol, 1, "-Deps"))
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 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021154 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021155 { # skip other symbols
21156 next;
21157 }
21158 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21159 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021160 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021161 next;
21162 }
21163 my $DyLib = $Symbol_Library{1}{$Symbol};
21164 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021165 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021166 next;
21167 }
21168 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21169 $Total+=1;
21170 }
21171 # Draw List
21172 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21173 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21174 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21175 {
21176 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21177 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021178 my %NS_Symbol = ();
21179 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021180 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021181 }
21182 foreach my $NameSpace (sort keys(%NS_Symbol))
21183 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021184 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021185 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21186 foreach my $Symbol (@SortedInterfaces)
21187 {
21188 my $SubReport = "";
21189 my $Signature = get_Signature($Symbol, 1);
21190 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021191 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021192 }
21193 if($Symbol=~/\A(_Z|\?)/)
21194 {
21195 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021196 $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 +040021197 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021198 else {
21199 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21200 }
21201 }
21202 else
21203 {
21204 if($Signature) {
21205 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21206 }
21207 else {
21208 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21209 }
21210 }
21211 $SYMBOLS_LIST .= $SubReport;
21212 }
21213 }
21214 $SYMBOLS_LIST .= "<br/>\n";
21215 }
21216 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021217 # clear info
21218 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21219 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21220 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21221 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021222 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021223 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021224 my $CssStyles = readModule("Styles", "SymbolsList.css");
21225 my $JScripts = readModule("Scripts", "Sections.js");
21226 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021227 my $Title = "$LName: public symbols";
21228 my $Keywords = "$LName, API, symbols";
21229 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021230 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021231 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021232 <br/><br/><hr/>\n".getReportFooter($LName, 1)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021233 <div style='height:999px;'></div></body></html>";
21234 writeFile($SaveTo, $SYMBOLS_LIST);
21235}
21236
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021237sub add_target_libs($)
21238{
21239 foreach (@{$_[0]}) {
21240 $TargetLibs{$_} = 1;
21241 }
21242}
21243
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021244sub is_target_lib($)
21245{
21246 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021247 if(not $LName) {
21248 return 0;
21249 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021250 if($TargetLibraryName
21251 and $LName!~/\Q$TargetLibraryName\E/) {
21252 return 0;
21253 }
21254 if(keys(%TargetLibs)
21255 and not $TargetLibs{$LName}
21256 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21257 return 0;
21258 }
21259 return 1;
21260}
21261
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021262sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021263{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021264 my ($H, $V) = @_;
21265 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021266 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021267 if($TargetHeaders{$V}{$H}) {
21268 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021269 }
21270 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021271 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021272}
21273
21274sub checkVersionNum($$)
21275{
21276 my ($LibVersion, $Path) = @_;
21277 if(my $VerNum = $TargetVersion{$LibVersion}) {
21278 return $VerNum;
21279 }
21280 my $UsedAltDescr = 0;
21281 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021282 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021283 next if(isDump($Part)); # ABI dump
21284 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021285 my $VerNum = "";
21286 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021287 {
21288 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021289 $VerNum = parse_libname($Part, "version", $OStarget);
21290 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021291 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021292 }
21293 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021294 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
21295 {
21296 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021297 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021298 }
21299 if($VerNum ne "")
21300 {
21301 $TargetVersion{$LibVersion} = $VerNum;
21302 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021303 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021304 }
21305 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021306 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 +040021307 }
21308 return $TargetVersion{$LibVersion};
21309 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021310 }
21311 if($UsedAltDescr)
21312 {
21313 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021314 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021315 }
21316 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021317 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021318 }
21319 }
21320}
21321
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021322sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021323{
21324 my $Str = $_[0];
21325 return "" if(not $Str);
21326 $Str=~s/\Q$TargetLibraryName\E//g;
21327 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021328 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021329 return $2;
21330 }
21331 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
21332 return $V;
21333 }
21334 return "";
21335}
21336
21337sub readLibs($)
21338{
21339 my $LibVersion = $_[0];
21340 if($OStarget eq "windows")
21341 { # dumpbin.exe will crash
21342 # without VS Environment
21343 check_win32_env();
21344 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021345 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021346 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021347 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021348}
21349
21350sub dump_sorting($)
21351{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021352 my $Hash = $_[0];
21353 return [] if(not $Hash);
21354 my @Keys = keys(%{$Hash});
21355 return [] if($#Keys<0);
21356 if($Keys[0]=~/\A\d+\Z/)
21357 { # numbers
21358 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021359 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021360 else
21361 { # strings
21362 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021363 }
21364}
21365
21366sub printMsg($$)
21367{
21368 my ($Type, $Msg) = @_;
21369 if($Type!~/\AINFO/) {
21370 $Msg = $Type.": ".$Msg;
21371 }
21372 if($Type!~/_C\Z/) {
21373 $Msg .= "\n";
21374 }
21375 if($Quiet)
21376 { # --quiet option
21377 appendFile($COMMON_LOG_PATH, $Msg);
21378 }
21379 else
21380 {
21381 if($Type eq "ERROR") {
21382 print STDERR $Msg;
21383 }
21384 else {
21385 print $Msg;
21386 }
21387 }
21388}
21389
21390sub exitStatus($$)
21391{
21392 my ($Code, $Msg) = @_;
21393 printMsg("ERROR", $Msg);
21394 exit($ERROR_CODE{$Code});
21395}
21396
21397sub exitReport()
21398{ # the tool has run without any errors
21399 printReport();
21400 if($COMPILE_ERRORS)
21401 { # errors in headers may add false positives/negatives
21402 exit($ERROR_CODE{"Compile_Error"});
21403 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021404 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21405 { # --binary
21406 exit($ERROR_CODE{"Incompatible"});
21407 }
21408 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21409 { # --source
21410 exit($ERROR_CODE{"Incompatible"});
21411 }
21412 elsif($RESULT{"Source"}{"Problems"}
21413 or $RESULT{"Binary"}{"Problems"})
21414 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021415 exit($ERROR_CODE{"Incompatible"});
21416 }
21417 else {
21418 exit($ERROR_CODE{"Compatible"});
21419 }
21420}
21421
21422sub readRules($)
21423{
21424 my $Kind = $_[0];
21425 if(not -f $RULES_PATH{$Kind}) {
21426 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21427 }
21428 my $Content = readFile($RULES_PATH{$Kind});
21429 while(my $Rule = parseTag(\$Content, "rule"))
21430 {
21431 my $RId = parseTag(\$Rule, "id");
21432 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21433 foreach my $Prop (@Properties) {
21434 if(my $Value = parseTag(\$Rule, lc($Prop)))
21435 {
21436 $Value=~s/\n[ ]*//;
21437 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21438 }
21439 }
21440 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21441 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21442 }
21443 else {
21444 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21445 }
21446 }
21447}
21448
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021449sub getReportPath($)
21450{
21451 my $Level = $_[0];
21452 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21453 if($Level eq "Binary")
21454 {
21455 if($BinaryReportPath)
21456 { # --bin-report-path
21457 return $BinaryReportPath;
21458 }
21459 elsif($OutputReportPath)
21460 { # --report-path
21461 return $OutputReportPath;
21462 }
21463 else
21464 { # default
21465 return $Dir."/abi_compat_report.$ReportFormat";
21466 }
21467 }
21468 elsif($Level eq "Source")
21469 {
21470 if($SourceReportPath)
21471 { # --src-report-path
21472 return $SourceReportPath;
21473 }
21474 elsif($OutputReportPath)
21475 { # --report-path
21476 return $OutputReportPath;
21477 }
21478 else
21479 { # default
21480 return $Dir."/src_compat_report.$ReportFormat";
21481 }
21482 }
21483 else
21484 {
21485 if($OutputReportPath)
21486 { # --report-path
21487 return $OutputReportPath;
21488 }
21489 else
21490 { # default
21491 return $Dir."/compat_report.$ReportFormat";
21492 }
21493 }
21494}
21495
21496sub printStatMsg($)
21497{
21498 my $Level = $_[0];
21499 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21500}
21501
21502sub listAffected($)
21503{
21504 my $Level = $_[0];
21505 my $List = "";
21506 foreach (keys(%{$TotalAffected{$Level}}))
21507 {
21508 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21509 { # skip "Low"-severity problems
21510 next;
21511 }
21512 $List .= "$_\n";
21513 }
21514 my $Dir = get_dirname(getReportPath($Level));
21515 if($Level eq "Binary") {
21516 writeFile($Dir."/abi_affected.txt", $List);
21517 }
21518 elsif($Level eq "Source") {
21519 writeFile($Dir."/src_affected.txt", $List);
21520 }
21521}
21522
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021523sub printReport()
21524{
21525 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021526 createReport();
21527 if($JoinReport or $DoubleReport)
21528 {
21529 if($RESULT{"Binary"}{"Problems"}
21530 or $RESULT{"Source"}{"Problems"}) {
21531 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021532 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021533 else {
21534 printMsg("INFO", "result: COMPATIBLE");
21535 }
21536 printStatMsg("Binary");
21537 printStatMsg("Source");
21538 if($ListAffected)
21539 { # --list-affected
21540 listAffected("Binary");
21541 listAffected("Source");
21542 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021543 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021544 elsif($BinaryOnly)
21545 {
21546 if($RESULT{"Binary"}{"Problems"}) {
21547 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21548 }
21549 else {
21550 printMsg("INFO", "result: COMPATIBLE");
21551 }
21552 printStatMsg("Binary");
21553 if($ListAffected)
21554 { # --list-affected
21555 listAffected("Binary");
21556 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021557 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021558 elsif($SourceOnly)
21559 {
21560 if($RESULT{"Source"}{"Problems"}) {
21561 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21562 }
21563 else {
21564 printMsg("INFO", "result: COMPATIBLE");
21565 }
21566 printStatMsg("Source");
21567 if($ListAffected)
21568 { # --list-affected
21569 listAffected("Source");
21570 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021571 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021572 if($StdOut)
21573 {
21574 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021575 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021576 printMsg("INFO", "compatibility report has been generated to stdout");
21577 }
21578 else
21579 { # default
21580 printMsg("INFO", "compatibility reports have been generated to stdout");
21581 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021582 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021583 else
21584 {
21585 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021586 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021587 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21588 }
21589 elsif($DoubleReport)
21590 { # default
21591 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21592 }
21593 elsif($BinaryOnly)
21594 { # --binary
21595 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21596 }
21597 elsif($SourceOnly)
21598 { # --source
21599 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21600 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021601 }
21602}
21603
21604sub check_win32_env()
21605{
21606 if(not $ENV{"DevEnvDir"}
21607 or not $ENV{"LIB"}) {
21608 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21609 }
21610}
21611
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021612sub diffSets($$)
21613{
21614 my ($S1, $S2) = @_;
21615 my @SK1 = keys(%{$S1});
21616 my @SK2 = keys(%{$S2});
21617 if($#SK1!=$#SK2) {
21618 return 1;
21619 }
21620 foreach my $K1 (@SK1)
21621 {
21622 if(not defined $S2->{$K1}) {
21623 return 1;
21624 }
21625 }
21626 return 0;
21627}
21628
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021629sub create_ABI_Dump()
21630{
21631 if(not -e $DumpAPI) {
21632 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21633 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021634 my @DParts = split(/\s*,\s*/, $DumpAPI);
21635 foreach my $Part (@DParts)
21636 {
21637 if(not -e $Part) {
21638 exitStatus("Access_Error", "can't access \'$Part\'");
21639 }
21640 }
21641 checkVersionNum(1, $DumpAPI);
21642 foreach my $Part (@DParts)
21643 {
21644 if(isDump($Part)) {
21645 read_ABI_Dump(1, $Part);
21646 }
21647 else {
21648 readDescriptor(1, createDescriptor(1, $Part));
21649 }
21650 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021651
21652 if(not $Descriptor{1}{"Version"})
21653 { # set to default: X
21654 $Descriptor{1}{"Version"} = "X";
21655 }
21656
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021657 initLogging(1);
21658 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021659
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021660 my $DumpPath = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi";
21661 $DumpPath .= ".".$AR_EXT; # gzipped by default
21662 if($OutputDumpPath)
21663 { # user defined path
21664 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021665 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021666 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21667
21668 if(not $Archive and not $StdOut)
21669 { # check archive utilities
21670 if($OSgroup eq "windows")
21671 { # using zip
21672 my $ZipCmd = get_CmdPath("zip");
21673 if(not $ZipCmd) {
21674 exitStatus("Not_Found", "can't find \"zip\"");
21675 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021676 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021677 else
21678 { # using tar and gzip
21679 my $TarCmd = get_CmdPath("tar");
21680 if(not $TarCmd) {
21681 exitStatus("Not_Found", "can't find \"tar\"");
21682 }
21683 my $GzipCmd = get_CmdPath("gzip");
21684 if(not $GzipCmd) {
21685 exitStatus("Not_Found", "can't find \"gzip\"");
21686 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021687 }
21688 }
21689
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021690 if(not $Descriptor{1}{"Dump"})
21691 {
21692 if(not $CheckHeadersOnly) {
21693 readLibs(1);
21694 }
21695 if($CheckHeadersOnly) {
21696 setLanguage(1, "C++");
21697 }
21698 if(not $CheckObjectsOnly) {
21699 searchForHeaders(1);
21700 }
21701 $WORD_SIZE{1} = detectWordSize();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021702 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021703 if(not $Descriptor{1}{"Dump"})
21704 {
21705 if($Descriptor{1}{"Headers"}) {
21706 readHeaders(1);
21707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021708 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021709 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021710 if(not keys(%{$SymbolInfo{1}}))
21711 { # check if created dump is valid
21712 if(not $ExtendedCheck and not $CheckObjectsOnly)
21713 {
21714 if($CheckHeadersOnly) {
21715 exitStatus("Empty_Set", "the set of public symbols is empty");
21716 }
21717 else {
21718 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21719 }
21720 }
21721 }
21722 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021723 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021724 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21725 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021726 if($ExtraDump)
21727 { # add unmangled names to the ABI dump
21728 my @Names = ();
21729 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21730 {
21731 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21732 push(@Names, $MnglName);
21733 }
21734 }
21735 translateSymbols(@Names, 1);
21736 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21737 {
21738 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21739 {
21740 if(my $Unmangled = $tr_name{$MnglName})
21741 {
21742 if($MnglName ne $Unmangled) {
21743 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21744 }
21745 }
21746 }
21747 }
21748 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021749
21750 my %GccConstants = (); # built-in GCC constants
21751 foreach my $Name (keys(%{$Constants{1}}))
21752 {
21753 if(not defined $Constants{1}{$Name}{"Header"})
21754 {
21755 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21756 delete($Constants{1}{$Name});
21757 }
21758 }
21759
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021760 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021761 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021762 "TypeInfo" => $TypeInfo{1},
21763 "SymbolInfo" => $SymbolInfo{1},
21764 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021765 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021766 "SymbolVersion" => $SymVer{1},
21767 "LibraryVersion" => $Descriptor{1}{"Version"},
21768 "LibraryName" => $TargetLibraryName,
21769 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021770 "SkipTypes" => $SkipTypes{1},
21771 "SkipSymbols" => $SkipSymbols{1},
21772 "SkipNameSpaces" => $SkipNameSpaces{1},
21773 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021774 "Headers" => \%HeadersInfo,
21775 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021776 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021777 "NameSpaces" => $NestedNameSpaces{1},
21778 "Target" => $OStarget,
21779 "Arch" => getArch(1),
21780 "WordSize" => $WORD_SIZE{1},
21781 "GccVersion" => get_dumpversion($GCC_PATH),
21782 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21783 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21784 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021785 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021786 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021787 }
21788 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021789 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021790 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021791 if($ExtendedCheck)
21792 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021793 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021794 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021795 if($BinaryOnly)
21796 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021797 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021798 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021799 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021800 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021801 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021802 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21803 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021804 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021805
21806 my $ABI_DUMP = "";
21807 if($UseXML)
21808 {
21809 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021810 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021811 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021812 else
21813 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021814 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021815 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021816 if($StdOut)
21817 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021818 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021819 printMsg("INFO", "ABI dump has been generated to stdout");
21820 return;
21821 }
21822 else
21823 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021824 my ($DDir, $DName) = separate_path($DumpPath);
21825 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021826 if(not $Archive) {
21827 $DPath = $DumpPath;
21828 }
21829
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021830 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021831
21832 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021833 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021834 close(DUMP);
21835
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021836 if(not -s $DPath) {
21837 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21838 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021839 if($Archive) {
21840 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021841 }
21842
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021843 if($OutputDumpPath) {
21844 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021845 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021846 else {
21847 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21848 }
21849 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 +040021850 }
21851}
21852
21853sub quickEmptyReports()
21854{ # Quick "empty" reports
21855 # 4 times faster than merging equal dumps
21856 # NOTE: the dump contains the "LibraryVersion" attribute
21857 # if you change the version, then your dump will be different
21858 # OVERCOME: use -v1 and v2 options for comparing dumps
21859 # and don't change version in the XML descriptor (and dumps)
21860 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21861 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21862 {
21863 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21864 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21865 if($FilePath1 and $FilePath2)
21866 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021867 my $Line = readLineNum($FilePath1, 0);
21868 if($Line=~/xml/)
21869 { # XML format
21870 # is not supported yet
21871 return;
21872 }
21873
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021874 local $/ = undef;
21875
21876 open(DUMP1, $FilePath1);
21877 my $Content1 = <DUMP1>;
21878 close(DUMP1);
21879
21880 open(DUMP2, $FilePath2);
21881 my $Content2 = <DUMP2>;
21882 close(DUMP2);
21883
21884 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021885 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021886 # clean memory
21887 undef $Content2;
21888
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021889 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021890 my $ABIdump = eval($Content1);
21891
21892 # clean memory
21893 undef $Content1;
21894
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021895 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021896 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 +040021897 }
21898 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021899 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021900 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21901 }
21902 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021903 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021904 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21905 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021906 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021907 read_Libs_DumpInfo($ABIdump, 1);
21908 read_Machine_DumpInfo($ABIdump, 1);
21909 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021910
21911 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21912 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21913
21914 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21915 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21916
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021917 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21918 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21919 exitReport();
21920 }
21921 }
21922 }
21923}
21924
21925sub initLogging($)
21926{
21927 my $LibVersion = $_[0];
21928 # create log directory
21929 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21930 if($OutputLogPath{$LibVersion})
21931 { # user-defined by -log-path option
21932 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21933 }
21934 if($LogMode ne "n") {
21935 mkpath($LOG_DIR);
21936 }
21937 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021938 if($Debug)
21939 { # debug directory
21940 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021941
21942 if(not $ExtraInfo)
21943 { # enable --extra-info
21944 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21945 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021946 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021947 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021948}
21949
21950sub writeLog($$)
21951{
21952 my ($LibVersion, $Msg) = @_;
21953 if($LogMode ne "n") {
21954 appendFile($LOG_PATH{$LibVersion}, $Msg);
21955 }
21956}
21957
21958sub resetLogging($)
21959{
21960 my $LibVersion = $_[0];
21961 if($LogMode!~/a|n/)
21962 { # remove old log
21963 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021964 if($Debug) {
21965 rmtree($DEBUG_PATH{$LibVersion});
21966 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021967 }
21968}
21969
21970sub printErrorLog($)
21971{
21972 my $LibVersion = $_[0];
21973 if($LogMode ne "n") {
21974 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21975 }
21976}
21977
21978sub isDump($)
21979{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021980 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz|\.zip|\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021981 return $1;
21982 }
21983 return 0;
21984}
21985
21986sub isDump_U($)
21987{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021988 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021989 return $1;
21990 }
21991 return 0;
21992}
21993
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021994sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021995{
21996 # read input XML descriptors or ABI dumps
21997 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021998 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021999 }
22000 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
22001 foreach my $Part (@DParts1)
22002 {
22003 if(not -e $Part) {
22004 exitStatus("Access_Error", "can't access \'$Part\'");
22005 }
22006 }
22007 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022008 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022009 }
22010 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
22011 foreach my $Part (@DParts2)
22012 {
22013 if(not -e $Part) {
22014 exitStatus("Access_Error", "can't access \'$Part\'");
22015 }
22016 }
22017 detect_default_paths("bin"); # to extract dumps
22018 if($#DParts1==0 and $#DParts2==0
22019 and isDump($Descriptor{1}{"Path"})
22020 and isDump($Descriptor{2}{"Path"}))
22021 { # optimization: equal ABI dumps
22022 quickEmptyReports();
22023 }
22024 checkVersionNum(1, $Descriptor{1}{"Path"});
22025 checkVersionNum(2, $Descriptor{2}{"Path"});
22026 printMsg("INFO", "preparation, please wait ...");
22027 foreach my $Part (@DParts1)
22028 {
22029 if(isDump($Part)) {
22030 read_ABI_Dump(1, $Part);
22031 }
22032 else {
22033 readDescriptor(1, createDescriptor(1, $Part));
22034 }
22035 }
22036 foreach my $Part (@DParts2)
22037 {
22038 if(isDump($Part)) {
22039 read_ABI_Dump(2, $Part);
22040 }
22041 else {
22042 readDescriptor(2, createDescriptor(2, $Part));
22043 }
22044 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022045
22046 if(not $Descriptor{1}{"Version"})
22047 { # set to default: X
22048 $Descriptor{1}{"Version"} = "X";
22049 }
22050
22051 if(not $Descriptor{2}{"Version"})
22052 { # set to default: Y
22053 $Descriptor{2}{"Version"} = "Y";
22054 }
22055
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022056 initLogging(1);
22057 initLogging(2);
22058 # check consistency
22059 if(not $Descriptor{1}{"Headers"}
22060 and not $Descriptor{1}{"Libs"}) {
22061 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
22062 }
22063 if(not $Descriptor{2}{"Headers"}
22064 and not $Descriptor{2}{"Libs"}) {
22065 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
22066 }
22067 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
22068 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
22069 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
22070 }
22071 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
22072 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
22073 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
22074 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022075 if(not $Descriptor{1}{"Headers"})
22076 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022077 if($CheckHeadersOnly_Opt) {
22078 exitStatus("Error", "can't find header files info in descriptor d1");
22079 }
22080 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022081 if(not $Descriptor{2}{"Headers"})
22082 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022083 if($CheckHeadersOnly_Opt) {
22084 exitStatus("Error", "can't find header files info in descriptor d2");
22085 }
22086 }
22087 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022088 or not $Descriptor{2}{"Headers"})
22089 {
22090 if(not $CheckObjectsOnly_Opt)
22091 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022092 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
22093 $CheckObjectsOnly = 1;
22094 }
22095 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022096 if(not $Descriptor{1}{"Libs"})
22097 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022098 if($CheckObjectsOnly_Opt) {
22099 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
22100 }
22101 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022102 if(not $Descriptor{2}{"Libs"})
22103 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022104 if($CheckObjectsOnly_Opt) {
22105 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
22106 }
22107 }
22108 if(not $Descriptor{1}{"Libs"}
22109 or not $Descriptor{2}{"Libs"})
22110 { # comparing standalone header files
22111 # comparing ABI dumps created with --headers-only
22112 if(not $CheckHeadersOnly_Opt)
22113 {
22114 printMsg("WARNING", "checking headers only");
22115 $CheckHeadersOnly = 1;
22116 }
22117 }
22118 if($UseDumps)
22119 { # --use-dumps
22120 # parallel processing
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022121 my $DumpPath1 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi.$AR_EXT";
22122 my $DumpPath2 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{2}{"Version"}.".abi.$AR_EXT";
22123
22124 unlink($DumpPath1);
22125 unlink($DumpPath2);
22126
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022127 my $pid = fork();
22128 if($pid)
22129 { # dump on two CPU cores
22130 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22131 if($RelativeDirectory{1}) {
22132 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22133 }
22134 if($OutputLogPath{1}) {
22135 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22136 }
22137 if($CrossGcc) {
22138 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22139 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022140 if($Quiet)
22141 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022142 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022143 @PARAMS = (@PARAMS, "-logging-mode", "a");
22144 }
22145 elsif($LogMode and $LogMode ne "w")
22146 { # "w" is default
22147 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022148 }
22149 if($ExtendedCheck) {
22150 @PARAMS = (@PARAMS, "-extended");
22151 }
22152 if($UserLang) {
22153 @PARAMS = (@PARAMS, "-lang", $UserLang);
22154 }
22155 if($TargetVersion{1}) {
22156 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22157 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022158 if($BinaryOnly) {
22159 @PARAMS = (@PARAMS, "-binary");
22160 }
22161 if($SourceOnly) {
22162 @PARAMS = (@PARAMS, "-source");
22163 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022164 if($SortDump) {
22165 @PARAMS = (@PARAMS, "-sort");
22166 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022167 if($DumpFormat and $DumpFormat ne "perl") {
22168 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22169 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022170 if($CheckHeadersOnly) {
22171 @PARAMS = (@PARAMS, "-headers-only");
22172 }
22173 if($CheckObjectsOnly) {
22174 @PARAMS = (@PARAMS, "-objects-only");
22175 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022176 if($Debug)
22177 {
22178 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022179 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022181 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022182 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022183 exit(1);
22184 }
22185 }
22186 else
22187 { # child
22188 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22189 if($RelativeDirectory{2}) {
22190 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22191 }
22192 if($OutputLogPath{2}) {
22193 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22194 }
22195 if($CrossGcc) {
22196 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22197 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022198 if($Quiet)
22199 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022200 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022201 @PARAMS = (@PARAMS, "-logging-mode", "a");
22202 }
22203 elsif($LogMode and $LogMode ne "w")
22204 { # "w" is default
22205 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022206 }
22207 if($ExtendedCheck) {
22208 @PARAMS = (@PARAMS, "-extended");
22209 }
22210 if($UserLang) {
22211 @PARAMS = (@PARAMS, "-lang", $UserLang);
22212 }
22213 if($TargetVersion{2}) {
22214 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22215 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022216 if($BinaryOnly) {
22217 @PARAMS = (@PARAMS, "-binary");
22218 }
22219 if($SourceOnly) {
22220 @PARAMS = (@PARAMS, "-source");
22221 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022222 if($SortDump) {
22223 @PARAMS = (@PARAMS, "-sort");
22224 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022225 if($DumpFormat and $DumpFormat ne "perl") {
22226 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22227 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022228 if($CheckHeadersOnly) {
22229 @PARAMS = (@PARAMS, "-headers-only");
22230 }
22231 if($CheckObjectsOnly) {
22232 @PARAMS = (@PARAMS, "-objects-only");
22233 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022234 if($Debug)
22235 {
22236 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022237 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022238 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022239 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022240 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022241 exit(1);
22242 }
22243 else {
22244 exit(0);
22245 }
22246 }
22247 waitpid($pid, 0);
22248 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022249 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22250 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022251 if($TargetLibraryFName ne $TargetLibraryName) {
22252 @CMP_PARAMS = (@CMP_PARAMS, "-l-full", $TargetLibraryFName);
22253 }
22254 if($ShowRetVal) {
22255 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22256 }
22257 if($CrossGcc) {
22258 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22259 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022260 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22261 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022262 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022263 }
22264 if($ReportFormat and $ReportFormat ne "html")
22265 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022266 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22267 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022268 if($OutputReportPath) {
22269 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22270 }
22271 if($BinaryReportPath) {
22272 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22273 }
22274 if($SourceReportPath) {
22275 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22276 }
22277 if($LoggingPath) {
22278 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22279 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022280 if($CheckHeadersOnly) {
22281 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22282 }
22283 if($CheckObjectsOnly) {
22284 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
22285 }
22286 if($BinaryOnly) {
22287 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22288 }
22289 if($SourceOnly) {
22290 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22291 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022292 if($Browse) {
22293 @CMP_PARAMS = (@CMP_PARAMS, "-browse", $Browse);
22294 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022295 if($OpenReport) {
22296 @CMP_PARAMS = (@CMP_PARAMS, "-open");
22297 }
22298 if($Debug)
22299 {
22300 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22301 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022302 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022303 system("perl", $0, @CMP_PARAMS);
22304 exit($?>>8);
22305 }
22306 if(not $Descriptor{1}{"Dump"}
22307 or not $Descriptor{2}{"Dump"})
22308 { # need GCC toolchain to analyze
22309 # header files and libraries
22310 detect_default_paths("inc|lib|gcc");
22311 }
22312 if(not $Descriptor{1}{"Dump"})
22313 {
22314 if(not $CheckHeadersOnly) {
22315 readLibs(1);
22316 }
22317 if($CheckHeadersOnly) {
22318 setLanguage(1, "C++");
22319 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022320 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022321 searchForHeaders(1);
22322 }
22323 $WORD_SIZE{1} = detectWordSize();
22324 }
22325 if(not $Descriptor{2}{"Dump"})
22326 {
22327 if(not $CheckHeadersOnly) {
22328 readLibs(2);
22329 }
22330 if($CheckHeadersOnly) {
22331 setLanguage(2, "C++");
22332 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022333 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022334 searchForHeaders(2);
22335 }
22336 $WORD_SIZE{2} = detectWordSize();
22337 }
22338 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22339 { # support for old ABI dumps
22340 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022341 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022342 {
22343 $WORD_SIZE{1} = $WORD_SIZE{2};
22344 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22345 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022346 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022347 {
22348 $WORD_SIZE{2} = $WORD_SIZE{1};
22349 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22350 }
22351 }
22352 elsif(not $WORD_SIZE{1}
22353 and not $WORD_SIZE{2})
22354 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022355 $WORD_SIZE{1} = "4";
22356 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022357 }
22358 if($Descriptor{1}{"Dump"})
22359 { # support for old ABI dumps
22360 prepareTypes(1);
22361 }
22362 if($Descriptor{2}{"Dump"})
22363 { # support for old ABI dumps
22364 prepareTypes(2);
22365 }
22366 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22367 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22368 }
22369 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022370 if(not $CheckObjectsOnly)
22371 {
22372 if($Descriptor{1}{"Headers"}
22373 and not $Descriptor{1}{"Dump"}) {
22374 readHeaders(1);
22375 }
22376 if($Descriptor{2}{"Headers"}
22377 and not $Descriptor{2}{"Dump"}) {
22378 readHeaders(2);
22379 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022380 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022381
22382 # clean memory
22383 %SystemHeaders = ();
22384 %mangled_name_gcc = ();
22385
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022386 prepareSymbols(1);
22387 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022388
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022389 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022390 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022391
22392 # Virtual Tables
22393 registerVTable(1);
22394 registerVTable(2);
22395
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022396 if(not checkDump(1, "1.22")
22397 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022398 { # support for old ABI dumps
22399 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22400 {
22401 if($ClassName=~/</)
22402 { # templates
22403 if(not defined $VirtualTable{1}{$ClassName})
22404 { # synchronize
22405 delete($VirtualTable{2}{$ClassName});
22406 }
22407 }
22408 }
22409 }
22410
22411 registerOverriding(1);
22412 registerOverriding(2);
22413
22414 setVirtFuncPositions(1);
22415 setVirtFuncPositions(2);
22416
22417 # Other
22418 addParamNames(1);
22419 addParamNames(2);
22420
22421 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022422}
22423
22424sub compareAPIs($)
22425{
22426 my $Level = $_[0];
22427 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022428 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022429 if($Level eq "Binary") {
22430 printMsg("INFO", "comparing ABIs ...");
22431 }
22432 else {
22433 printMsg("INFO", "comparing APIs ...");
22434 }
22435 if($CheckHeadersOnly
22436 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022437 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022438 detectAdded_H($Level);
22439 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022440 }
22441 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022442 { # added/removed in libs
22443 detectAdded($Level);
22444 detectRemoved($Level);
22445 }
22446 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022447 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022448 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022449 if(keys(%{$CheckedSymbols{$Level}})) {
22450 mergeConstants($Level);
22451 }
22452 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022453
22454 $Cache{"mergeTypes"} = (); # free memory
22455
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022456 if($CheckHeadersOnly
22457 or $Level eq "Source")
22458 { # added/removed in headers
22459 mergeHeaders($Level);
22460 }
22461 else
22462 { # added/removed in libs
22463 mergeLibs($Level);
22464 if($CheckImpl
22465 and $Level eq "Binary") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022466 mergeImpl();
22467 }
22468 }
22469}
22470
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022471sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022472{
22473 my %Opts = (
22474 "OStarget"=>$OStarget,
22475 "Debug"=>$Debug,
22476 "Quiet"=>$Quiet,
22477 "LogMode"=>$LogMode,
22478 "CheckHeadersOnly"=>$CheckHeadersOnly,
22479
22480 "SystemRoot"=>$SystemRoot,
22481 "MODULES_DIR"=>$MODULES_DIR,
22482 "GCC_PATH"=>$GCC_PATH,
22483 "TargetSysInfo"=>$TargetSysInfo,
22484 "CrossPrefix"=>$CrossPrefix,
22485 "TargetLibraryName"=>$TargetLibraryName,
22486 "CrossGcc"=>$CrossGcc,
22487 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022488 "NoStdInc"=>$NoStdInc,
22489
22490 "BinaryOnly" => $BinaryOnly,
22491 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022492 );
22493 return \%Opts;
22494}
22495
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022496sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022497{
22498 my %CODE_ERROR = reverse(%ERROR_CODE);
22499 return $CODE_ERROR{$_[0]};
22500}
22501
22502sub scenario()
22503{
22504 if($StdOut)
22505 { # enable quiet mode
22506 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022507 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022508 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022509 if(not $LogMode)
22510 { # default
22511 $LogMode = "w";
22512 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022513 if($UserLang)
22514 { # --lang=C++
22515 $UserLang = uc($UserLang);
22516 $COMMON_LANGUAGE{1}=$UserLang;
22517 $COMMON_LANGUAGE{2}=$UserLang;
22518 }
22519 if($LoggingPath)
22520 {
22521 $OutputLogPath{1} = $LoggingPath;
22522 $OutputLogPath{2} = $LoggingPath;
22523 if($Quiet) {
22524 $COMMON_LOG_PATH = $LoggingPath;
22525 }
22526 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022527 if($Quick) {
22528 $ADD_TMPL_INSTANCES = 0;
22529 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022530 if($OutputDumpPath)
22531 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022532 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022533 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22534 }
22535 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022536 if($BinaryOnly and $SourceOnly)
22537 { # both --binary and --source
22538 # is the default mode
22539 $DoubleReport = 1;
22540 $JoinReport = 0;
22541 $BinaryOnly = 0;
22542 $SourceOnly = 0;
22543 if($OutputReportPath)
22544 { # --report-path
22545 $DoubleReport = 0;
22546 $JoinReport = 1;
22547 }
22548 }
22549 elsif($BinaryOnly or $SourceOnly)
22550 { # --binary or --source
22551 $DoubleReport = 0;
22552 $JoinReport = 0;
22553 }
22554 if($UseXML)
22555 { # --xml option
22556 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022557 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022558 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022559 if($ReportFormat)
22560 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022561 $ReportFormat = lc($ReportFormat);
22562 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022563 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022564 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022565 if($ReportFormat eq "htm")
22566 { # HTM == HTML
22567 $ReportFormat = "html";
22568 }
22569 elsif($ReportFormat eq "xml")
22570 { # --report-format=XML equal to --xml
22571 $UseXML = 1;
22572 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022573 }
22574 else
22575 { # default: HTML
22576 $ReportFormat = "html";
22577 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022578 if($DumpFormat)
22579 { # validate
22580 $DumpFormat = lc($DumpFormat);
22581 if($DumpFormat!~/\A(xml|perl)\Z/) {
22582 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22583 }
22584 if($DumpFormat eq "xml")
22585 { # --dump-format=XML equal to --xml
22586 $UseXML = 1;
22587 }
22588 }
22589 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022590 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022591 $DumpFormat = "perl";
22592 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022593 if($Quiet and $LogMode!~/a|n/)
22594 { # --quiet log
22595 if(-f $COMMON_LOG_PATH) {
22596 unlink($COMMON_LOG_PATH);
22597 }
22598 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022599 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022600 $CheckUndefined = 1;
22601 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022602 if($TestTool and $UseDumps)
22603 { # --test && --use-dumps == --test-dump
22604 $TestDump = 1;
22605 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022606 if($Tolerant)
22607 { # enable all
22608 $Tolerance = 1234;
22609 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022610 if($Help)
22611 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022612 HELP_MESSAGE();
22613 exit(0);
22614 }
22615 if($InfoMsg) {
22616 INFO_MESSAGE();
22617 exit(0);
22618 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022619 if($ShowVersion)
22620 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022621 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.");
22622 exit(0);
22623 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022624 if($DumpVersion)
22625 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022626 printMsg("INFO", $TOOL_VERSION);
22627 exit(0);
22628 }
22629 if($ExtendedCheck) {
22630 $CheckHeadersOnly = 1;
22631 }
22632 if($SystemRoot_Opt)
22633 { # user defined root
22634 if(not -e $SystemRoot_Opt) {
22635 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22636 }
22637 $SystemRoot = $SystemRoot_Opt;
22638 $SystemRoot=~s/[\/]+\Z//g;
22639 if($SystemRoot) {
22640 $SystemRoot = get_abs_path($SystemRoot);
22641 }
22642 }
22643 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022644
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022645 if($SortDump)
22646 {
22647 $Data::Dumper::Useperl = 1;
22648 $Data::Dumper::Sortkeys = \&dump_sorting;
22649 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022650
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022651 if($TargetLibsPath)
22652 {
22653 if(not -f $TargetLibsPath) {
22654 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22655 }
22656 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22657 $TargetLibs{$Lib} = 1;
22658 }
22659 }
22660 if($TargetHeadersPath)
22661 { # --headers-list
22662 if(not -f $TargetHeadersPath) {
22663 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22664 }
22665 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22666 {
22667 $TargetHeaders{1}{$Header} = 1;
22668 $TargetHeaders{2}{$Header} = 1;
22669 }
22670 }
22671 if($TargetHeader)
22672 { # --header
22673 $TargetHeaders{1}{$TargetHeader} = 1;
22674 $TargetHeaders{2}{$TargetHeader} = 1;
22675 }
22676 if($TestTool
22677 or $TestDump)
22678 { # --test, --test-dump
22679 detect_default_paths("bin|gcc"); # to compile libs
22680 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022681 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
22682 $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022683 exit(0);
22684 }
22685 if($DumpSystem)
22686 { # --dump-system
22687 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022688 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022689 { # system XML descriptor
22690 if(not -f $DumpSystem) {
22691 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22692 }
22693 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022694 foreach (@{$Ret->{"Tools"}})
22695 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022696 push_U($SystemPaths{"bin"}, $_);
22697 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022698 }
22699 if($Ret->{"CrossPrefix"}) {
22700 $CrossPrefix = $Ret->{"CrossPrefix"};
22701 }
22702 }
22703 elsif($SystemRoot_Opt)
22704 { # -sysroot "/" option
22705 # default target: /usr/lib, /usr/include
22706 # search libs: /usr/lib and /lib
22707 if(not -e $SystemRoot."/usr/lib") {
22708 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22709 }
22710 if(not -e $SystemRoot."/lib") {
22711 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22712 }
22713 if(not -e $SystemRoot."/usr/include") {
22714 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22715 }
22716 readSystemDescriptor("
22717 <name>
22718 $DumpSystem
22719 </name>
22720 <headers>
22721 $SystemRoot/usr/include
22722 </headers>
22723 <libs>
22724 $SystemRoot/usr/lib
22725 </libs>
22726 <search_libs>
22727 $SystemRoot/lib
22728 </search_libs>");
22729 }
22730 else {
22731 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22732 }
22733 detect_default_paths("bin|gcc"); # to check symbols
22734 if($OStarget eq "windows")
22735 { # to run dumpbin.exe
22736 # and undname.exe
22737 check_win32_env();
22738 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022739 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022740 exit(0);
22741 }
22742 if($CmpSystems)
22743 { # --cmp-systems
22744 detect_default_paths("bin"); # to extract dumps
22745 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022746 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022747 exit(0);
22748 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022749 if($GenerateTemplate)
22750 {
22751 writeFile("VERSION.xml", $DescriptorTemplate."\n");
22752 printMsg("INFO", "XML-descriptor template ./VERSION.xml has been generated");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022753 exit(0);
22754 }
22755 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022756 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022757 }
22758 else
22759 { # validate library name
22760 if($TargetLibraryName=~/[\*\/\\]/) {
22761 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22762 }
22763 }
22764 if(not $TargetLibraryFName) {
22765 $TargetLibraryFName = $TargetLibraryName;
22766 }
22767 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
22768 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
22769 }
22770 if($SymbolsListPath)
22771 {
22772 if(not -f $SymbolsListPath) {
22773 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22774 }
22775 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22776 $SymbolsList{$Interface} = 1;
22777 }
22778 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022779 if($SkipSymbolsListPath)
22780 {
22781 if(not -f $SkipSymbolsListPath) {
22782 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22783 }
22784 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
22785 $SkipSymbolsList{$Interface} = 1;
22786 }
22787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022788 if($SkipHeadersPath)
22789 {
22790 if(not -f $SkipHeadersPath) {
22791 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22792 }
22793 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022794 { # register for both versions
22795 $SkipHeadersList{1}{$Path} = 1;
22796 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022797 my ($CPath, $Type) = classifyPath($Path);
22798 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022799 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022800 }
22801 }
22802 if($ParamNamesPath)
22803 {
22804 if(not -f $ParamNamesPath) {
22805 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22806 }
22807 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22808 {
22809 if($Line=~s/\A(\w+)\;//)
22810 {
22811 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022812 if($Line=~/;(\d+);/)
22813 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022814 while($Line=~s/(\d+);(\w+)//) {
22815 $AddIntParams{$Interface}{$1}=$2;
22816 }
22817 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022818 else
22819 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022820 my $Num = 0;
22821 foreach my $Name (split(/;/, $Line)) {
22822 $AddIntParams{$Interface}{$Num++}=$Name;
22823 }
22824 }
22825 }
22826 }
22827 }
22828 if($AppPath)
22829 {
22830 if(not -f $AppPath) {
22831 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22832 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022833 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022834 $SymbolsList_App{$Interface} = 1;
22835 }
22836 }
22837 if($DumpAPI)
22838 { # --dump-abi
22839 # make an API dump
22840 create_ABI_Dump();
22841 exit($COMPILE_ERRORS);
22842 }
22843 # default: compare APIs
22844 # -d1 <path>
22845 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022846 compareInit();
22847 if($JoinReport or $DoubleReport)
22848 {
22849 compareAPIs("Binary");
22850 compareAPIs("Source");
22851 }
22852 elsif($BinaryOnly) {
22853 compareAPIs("Binary");
22854 }
22855 elsif($SourceOnly) {
22856 compareAPIs("Source");
22857 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022858 exitReport();
22859}
22860
22861scenario();