blob: e10741f5f09b0e05688b9fba1c46a9192421e683 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03003# ABI Compliance Checker (ABICC) 1.99.10
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-2011 Institute for System Programming, RAS
7# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03008# Copyright (C) 2012-2013 ROSA Laboratory
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +03009# Copyright (C) 2013-2015 Andrey Ponomarenko's ABI 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 Ponomarenkoc5221342014-09-24 16:43:03 +040020# - G++ (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021# - GNU Binutils (readelf, c++filt, objdump)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022# - Perl 5 (5.8 or newer)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040024#
25# Mac OS X
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040026# - Xcode (g++, c++filt, otool, nm)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040027# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040028#
29# MS Windows
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040030# - MinGW (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040031# - MS Visual C++ (dumpbin, undname, cl)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040032# - Active Perl 5 (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040033# - Sigcheck v1.71 or newer
34# - Info-ZIP 3.0 (zip, unzip)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040035# - Ctags (5.8 or newer)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040036# - Add tool locations to the PATH environment variable
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040037# - Run vsvars32.bat (C:\Microsoft Visual Studio 9.0\Common7\Tools\)
38#
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040039# COMPATIBILITY
40# =============
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030041# ABI Dumper >= 0.99.9
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 Ponomarenko52b2e352015-08-11 22:45:36 +030067my $TOOL_VERSION = "1.99.10";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040068my $ABI_DUMP_VERSION = "3.2";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040069my $XML_REPORT_VERSION = "1.2";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040070my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040071my $OSgroup = get_OSgroup();
72my $ORIG_DIR = cwd();
73my $TMP_DIR = tempdir(CLEANUP=>1);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030074my $LOCALE = "C.UTF-8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040075
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
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030084my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040085$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
86$CheckObjectsOnly_Opt, $AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030087%RelativeDirectory, $TargetTitle, $TestDump, $LoggingPath,
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030088%TargetVersion, $InfoMsg, $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 Ponomarenko52b2e352015-08-11 22:45:36 +030094$SourceReportPath, $UseXML, $SortDump, $DumpFormat,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040095$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040096$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CppIncompat, $SkipInternal,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030097$TargetArch, $GccOptions, $TypesListPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040098
99my $CmdName = get_filename($0);
100my %OS_LibExt = (
101 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400102 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400103 "macos"=>"dylib",
104 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400105 "symbian"=>"dso",
106 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400107 },
108 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400109 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400110 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400111 "symbian"=>"lib",
112 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400113 }
114);
115
116my %OS_Archive = (
117 "windows"=>"zip",
118 "default"=>"tar.gz"
119);
120
121my %ERROR_CODE = (
122 # Compatible verdict
123 "Compatible"=>0,
124 "Success"=>0,
125 # Incompatible verdict
126 "Incompatible"=>1,
127 # Undifferentiated error code
128 "Error"=>2,
129 # System command is not found
130 "Not_Found"=>3,
131 # Cannot access input files
132 "Access_Error"=>4,
133 # Cannot compile header files
134 "Cannot_Compile"=>5,
135 # Header compiled with errors
136 "Compile_Error"=>6,
137 # Invalid input ABI dump
138 "Invalid_Dump"=>7,
139 # Incompatible version of ABI dump
140 "Dump_Version"=>8,
141 # Cannot find a module
142 "Module_Error"=>9,
143 # Empty intersection between
144 # headers and shared objects
145 "Empty_Intersection"=>10,
146 # Empty set of symbols in headers
147 "Empty_Set"=>11
148);
149
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300150my $HomePage = "http://lvc.github.io/abi-compliance-checker/";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400151
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400152my $ShortUsage = "ABI Compliance Checker (ABICC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400153A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300154Copyright (C) 2015 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400155License: GNU LGPL or GNU GPL
156
157Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400158Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400159
160OLD.xml and NEW.xml are XML-descriptors:
161
162 <version>
163 1.0
164 </version>
165
166 <headers>
167 /path/to/headers/
168 </headers>
169
170 <libs>
171 /path/to/libraries/
172 </libs>
173
174More info: $CmdName --help\n";
175
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400176if($#ARGV==-1)
177{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400178 printMsg("INFO", $ShortUsage);
179 exit(0);
180}
181
182foreach (2 .. $#ARGV)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400183{ # correct comma separated options
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400184 if($ARGV[$_-1] eq ",")
185 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400186 $ARGV[$_-2].=",".$ARGV[$_];
187 splice(@ARGV, $_-1, 2);
188 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400189 elsif($ARGV[$_-1]=~/,\Z/)
190 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400191 $ARGV[$_-1].=$ARGV[$_];
192 splice(@ARGV, $_, 1);
193 }
194 elsif($ARGV[$_]=~/\A,/
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400195 and $ARGV[$_] ne ",")
196 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400197 $ARGV[$_-1].=$ARGV[$_];
198 splice(@ARGV, $_, 1);
199 }
200}
201
202GetOptions("h|help!" => \$Help,
203 "i|info!" => \$InfoMsg,
204 "v|version!" => \$ShowVersion,
205 "dumpversion!" => \$DumpVersion,
206# general options
207 "l|lib|library=s" => \$TargetLibraryName,
208 "d1|old|o=s" => \$Descriptor{1}{"Path"},
209 "d2|new|n=s" => \$Descriptor{2}{"Path"},
210 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400211# extra options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400212 "app|application=s" => \$AppPath,
213 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +0400214 "gcc-path|cross-gcc=s" => \$CrossGcc,
215 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
216 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400217 "sysroot=s" => \$SystemRoot_Opt,
218 "v1|version1|vnum=s" => \$TargetVersion{1},
219 "v2|version2=s" => \$TargetVersion{2},
220 "s|strict!" => \$StrictCompat,
221 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300222 "types-list=s" => \$TypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400223 "skip-symbols=s" => \$SkipSymbolsListPath,
224 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400225 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400226 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400227 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
228 "objects-only!" => \$CheckObjectsOnly_Opt,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400229 "show-retval!" => \$ShowRetVal,
230 "use-dumps!" => \$UseDumps,
231 "nostdinc!" => \$NoStdInc,
232 "dump-system=s" => \$DumpSystem,
233 "sysinfo=s" => \$TargetSysInfo,
234 "cmp-systems!" => \$CmpSystems,
235 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400236 "ext|extended!" => \$ExtendedCheck,
237 "q|quiet!" => \$Quiet,
238 "stdout!" => \$StdOut,
239 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400240 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400241 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400242 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400243 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400244 "binary|bin|abi!" => \$BinaryOnly,
245 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400246 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400247# other options
248 "test!" => \$TestTool,
249 "test-dump!" => \$TestDump,
250 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400251 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400252 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400253 "p|params=s" => \$ParamNamesPath,
254 "relpath1|relpath=s" => \$RelativeDirectory{1},
255 "relpath2=s" => \$RelativeDirectory{2},
256 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400257 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400258 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400259 "bin-report-path=s" => \$BinaryReportPath,
260 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400261 "log-path=s" => \$LoggingPath,
262 "log1-path=s" => \$OutputLogPath{1},
263 "log2-path=s" => \$OutputLogPath{2},
264 "logging-mode=s" => \$LogMode,
265 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300266 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400267 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400268 "extra-info=s" => \$ExtraInfo,
269 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400270 "force!" => \$Force,
271 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400272 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400273 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400274 "quick!" => \$Quick,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400275 "all-affected!" => \$AllAffected,
276 "skip-internal=s" => \$SkipInternal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400277) or ERR_MESSAGE();
278
279sub ERR_MESSAGE()
280{
281 printMsg("INFO", "\n".$ShortUsage);
282 exit($ERROR_CODE{"Error"});
283}
284
285my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
286my $SLIB_TYPE = $LIB_TYPE;
287if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
288{ # show as "shared" library
289 $SLIB_TYPE = "shared";
290}
291my $LIB_EXT = getLIB_EXT($OSgroup);
292my $AR_EXT = getAR_EXT($OSgroup);
293my $BYTE_SIZE = 8;
294my $COMMON_LOG_PATH = "logs/run.log";
295
296my $HelpMessage="
297NAME:
298 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400299 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400300
301DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400302 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400303 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
304 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
305 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
306 and/or source-level compatibility: changes in calling stack, v-table changes,
307 removed symbols, renamed fields, etc. Binary incompatibility may result in
308 crashing or incorrect behavior of applications built with an old version of
309 a library if they run on a new one. Source incompatibility may result in
310 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400311
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400312 The tool is intended for developers of software libraries and maintainers
313 of operating systems who are interested in ensuring backward compatibility,
314 i.e. allow old applications to run or to be recompiled with newer library
315 versions.
316
317 Also the tool can be used by ISVs for checking applications portability to
318 new library versions. Found issues can be taken into account when adapting
319 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400320
321 This tool is free software: you can redistribute it and/or modify it
322 under the terms of the GNU LGPL or GNU GPL.
323
324USAGE:
325 $CmdName [options]
326
327EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400328 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400329
330 OLD.xml and NEW.xml are XML-descriptors:
331
332 <version>
333 1.0
334 </version>
335
336 <headers>
337 /path1/to/header(s)/
338 /path2/to/header(s)/
339 ...
340 </headers>
341
342 <libs>
343 /path1/to/library(ies)/
344 /path2/to/library(ies)/
345 ...
346 </libs>
347
348INFORMATION OPTIONS:
349 -h|-help
350 Print this help.
351
352 -i|-info
353 Print complete info.
354
355 -v|-version
356 Print version information.
357
358 -dumpversion
359 Print the tool version ($TOOL_VERSION) and don't do anything else.
360
361GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400362 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400363 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400364
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400365 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400366 Descriptor of 1st (old) library version.
367 It may be one of the following:
368
369 1. XML-descriptor (VERSION.xml file):
370
371 <version>
372 1.0
373 </version>
374
375 <headers>
376 /path1/to/header(s)/
377 /path2/to/header(s)/
378 ...
379 </headers>
380
381 <libs>
382 /path1/to/library(ies)/
383 /path2/to/library(ies)/
384 ...
385 </libs>
386
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300387 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400388
389 2. ABI dump generated by -dump option
390 3. Directory with headers and/or $SLIB_TYPE libraries
391 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400392
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300393 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400394 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400395
396 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400397 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400398
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400399 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400400 Descriptor of 2nd (new) library version.
401
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400402 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400403 Create library ABI dump for the input XML descriptor. You can
404 transfer it anywhere and pass instead of the descriptor. Also
405 it can be used for debugging the tool.
406
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300407 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400408
409sub HELP_MESSAGE() {
410 printMsg("INFO", $HelpMessage."
411MORE INFO:
412 $CmdName --info\n");
413}
414
415sub INFO_MESSAGE()
416{
417 printMsg("INFO", "$HelpMessage
418EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400419 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300420 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400421 for portability to the new library version.
422
423 -static-libs
424 Check static libraries instead of the shared ones. The <libs> section
425 of the XML-descriptor should point to static libraries location.
426
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400427 -cross-gcc|-gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400428 Path to the cross GCC compiler to use instead of the usual (host) GCC.
429
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400430 -cross-prefix|-gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400431 GCC toolchain prefix.
432
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400433 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400434 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400435 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400436
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400437 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400438 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200439 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400440
441 In general case you should specify it in the XML-descriptor:
442 <version>
443 VERSION
444 </version>
445
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400446 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400447 Specify 2nd library version outside the descriptor.
448
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400449 -vnum NUM
450 Specify the library version in the generated ABI dump. The <version> section
451 of the input XML descriptor will be overwritten in this case.
452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400453 -s|-strict
454 Treat all compatibility warnings as problems. Add a number of \"Low\"
455 severity problems to the return value of the tool.
456
457 -headers-only
458 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
459 provide a low quality compatibility report with false positives and
460 without detecting of added/removed symbols.
461
462 Alternatively you can write \"none\" word to the <libs> section
463 in the XML-descriptor:
464 <libs>
465 none
466 </libs>
467
468 -objects-only
469 Check $SLIB_TYPE libraries without header files. It is easy to run, but may
470 provide a low quality compatibility report with false positives and
471 without analysis of changes in parameters and data types.
472
473 Alternatively you can write \"none\" word to the <headers> section
474 in the XML-descriptor:
475 <headers>
476 none
477 </headers>
478
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400479 -show-retval
480 Show the symbol's return type in the report.
481
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400482 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300483 This option allows to specify a file with a list of symbols (mangled
484 names in C++) that should be checked. Other symbols will not be checked.
485
486 -types-list PATH
487 This option allows to specify a file with a list of types that should
488 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400489
490 -skip-symbols PATH
491 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400492
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400493 -headers-list PATH
494 The file with a list of headers, that should be checked/dumped.
495
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400496 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400497 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400498
499 -header NAME
500 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400501
502 -use-dumps
503 Make dumps for two versions of a library and compare dumps. This should
504 increase the performance of the tool and decrease the system memory usage.
505
506 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400507 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400508
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400509 -dump-system NAME -sysroot DIR
510 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400511 create XML descriptors and make ABI dumps for each library. The result
512 set of ABI dumps can be compared (--cmp-systems) with the other one
513 created for other version of operating system in order to check them for
514 compatibility. Do not forget to specify -cross-gcc option if your target
515 system requires some specific version of GCC compiler (different from
516 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400517 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400518
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400519 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400520 The same as the previous option but takes an XML descriptor of the target
521 system as input, where you should describe it:
522
523 /* Primary sections */
524
525 <name>
526 /* Name of the system */
527 </name>
528
529 <headers>
530 /* The list of paths to header files and/or
531 directories with header files, one per line */
532 </headers>
533
534 <libs>
535 /* The list of paths to shared libraries and/or
536 directories with shared libraries, one per line */
537 </libs>
538
539 /* Optional sections */
540
541 <search_headers>
542 /* List of directories to be searched
543 for header files to automatically
544 generate include paths, one per line */
545 </search_headers>
546
547 <search_libs>
548 /* List of directories to be searched
549 for shared libraries to resolve
550 dependencies, one per line */
551 </search_libs>
552
553 <tools>
554 /* List of directories with tools used
555 for analysis (GCC toolchain), one per line */
556 </tools>
557
558 <cross_prefix>
559 /* GCC toolchain prefix.
560 Examples:
561 arm-linux-gnueabi
562 arm-none-symbianelf */
563 </cross_prefix>
564
565 <gcc_options>
566 /* Additional GCC options, one per line */
567 </gcc_options>
568
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400569 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300570 This option should be used with -dump-system option to dump
571 ABI of operating systems and configure the dumping process.
572 You can find a sample in the package:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400573 modules/Targets/{unix, symbian, windows}
574
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400575 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400576 Compare two system ABI dumps. Create compatibility reports for each
577 library and the common HTML report including the summary of test
578 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400579 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400580
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400581 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400582 The file with a list of libraries, that should be dumped by
583 the -dump-system option or should be checked by the -cmp-systems option.
584
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400585 -ext|-extended
586 If your library A is supposed to be used by other library B and you
587 want to control the ABI of B, then you should enable this option. The
588 tool will check for changes in all data types, even if they are not
589 used by any function in the library A. Such data types are not part
590 of the A library ABI, but may be a part of the ABI of the B library.
591
592 The short scheme is:
593 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
594
595 -q|-quiet
596 Print all messages to the file instead of stdout and stderr.
597 Default path (can be changed by -log-path option):
598 $COMMON_LOG_PATH
599
600 -stdout
601 Print analysis results (compatibility reports and ABI dumps) to stdout
602 instead of creating a file. This would allow piping data to other programs.
603
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400604 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400605 Change format of compatibility report.
606 Formats:
607 htm - HTML format (default)
608 xml - XML format
609
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400610 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400611 Change format of ABI dump.
612 Formats:
613 perl - Data::Dumper format (default)
614 xml - XML format
615
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400616 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400617 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400618
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400619 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400620 Set library language (C or C++). You can use this option if the tool
621 cannot auto-detect a language. This option may be useful for checking
622 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400623
624 -arch ARCH
625 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
626 ect.). The option is useful if the tool cannot detect correct architecture
627 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400628
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400629 -binary|-bin|-abi
630 Show \"Binary\" compatibility problems only.
631 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400632 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400633
634 -source|-src|-api
635 Show \"Source\" compatibility problems only.
636 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400637 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400638
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400639 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400640 The maximum number of affected symbols listed under the description
641 of the changed type in the report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400642
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400643OTHER OPTIONS:
644 -test
645 Run internal tests. Create two binary incompatible versions of a sample
646 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300647 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400648
649 -test-dump
650 Test ability to create, read and compare ABI dumps.
651
652 -debug
653 Debugging mode. Print debug info on the screen. Save intermediate
654 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400655 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400656
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400657 Also consider using --dump option for debugging the tool.
658
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400659 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400660 If your header files are written in C language and can be compiled
661 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
662 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400663
664 -cpp-incompatible
665 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400666
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400667 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400668 Path to file with the function parameter names. It can be used
669 for improving report view if the library header files have no
670 parameter names. File format:
671
672 func1;param1;param2;param3 ...
673 func2;param1;param2;param3 ...
674 ...
675
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400676 -relpath PATH
677 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400678 for dumping the library ABI (see -dump option).
679
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400680 -relpath1 PATH
681 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400682
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400683 -relpath2 PATH
684 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400685
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400686 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400687 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400688 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400689 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400690
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400691 -sort
692 Enable sorting of data in ABI dumps.
693
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400694 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400695 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400696 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400697 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400698
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400699 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400700 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400701 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400702 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400703
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400704 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400705 Path to \"Source\" compatibility report.
706 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400707 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400708
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400709 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400710 Log path for all messages.
711 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400712 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400713
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400714 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400715 Log path for 1st version of a library.
716 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400717 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400718
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400719 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400720 Log path for 2nd version of a library.
721 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400722 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400723
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400724 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400725 Change logging mode.
726 Modes:
727 w - overwrite old logs (default)
728 a - append old logs
729 n - do not write any logs
730
731 -list-affected
732 Generate file with the list of incompatible
733 symbols beside the HTML compatibility report.
734 Use 'c++filt \@file' command from GNU binutils
735 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400736 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400737 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400738 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400739
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400740 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400741 The component name in the title and summary of the HTML report.
742 Default:
743 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300744
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300745 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400746 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400747 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400748
749 -extra-info DIR
750 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400751
752 -extra-dump
753 Create extended ABI dump containing all symbols
754 from the translation unit.
755
756 -force
757 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400758
759 -tolerance LEVEL
760 Apply a set of heuristics to successfully compile input
761 header files. You can enable several tolerance levels by
762 joining them into one string (e.g. 13, 124, etc.).
763 Levels:
764 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
765 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
766 3 - skip headers that iclude non-Linux headers
767 4 - skip headers included by others
768
769 -tolerant
770 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400771
772 -check
773 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400774
775 -quick
776 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400777
778 -skip-internal PATTERN
779 Do not check internal interfaces matched by the pattern.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400780
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400781REPORT:
782 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400783 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400784
785 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400786 logs/LIB_NAME/V1/log.txt
787 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400788
789EXIT CODES:
790 0 - Compatible. The tool has run without any errors.
791 non-zero - Incompatible or the tool has run with errors.
792
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400793MORE INFORMATION:
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300794 ".$HomePage."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400795}
796
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400797my %Operator_Indication = (
798 "not" => "~",
799 "assign" => "=",
800 "andassign" => "&=",
801 "orassign" => "|=",
802 "xorassign" => "^=",
803 "or" => "|",
804 "xor" => "^",
805 "addr" => "&",
806 "and" => "&",
807 "lnot" => "!",
808 "eq" => "==",
809 "ne" => "!=",
810 "lt" => "<",
811 "lshift" => "<<",
812 "lshiftassign" => "<<=",
813 "rshiftassign" => ">>=",
814 "call" => "()",
815 "mod" => "%",
816 "modassign" => "%=",
817 "subs" => "[]",
818 "land" => "&&",
819 "lor" => "||",
820 "rshift" => ">>",
821 "ref" => "->",
822 "le" => "<=",
823 "deref" => "*",
824 "mult" => "*",
825 "preinc" => "++",
826 "delete" => " delete",
827 "vecnew" => " new[]",
828 "vecdelete" => " delete[]",
829 "predec" => "--",
830 "postinc" => "++",
831 "postdec" => "--",
832 "plusassign" => "+=",
833 "plus" => "+",
834 "minus" => "-",
835 "minusassign" => "-=",
836 "gt" => ">",
837 "ge" => ">=",
838 "new" => " new",
839 "multassign" => "*=",
840 "divassign" => "/=",
841 "div" => "/",
842 "neg" => "-",
843 "pos" => "+",
844 "memref" => "->*",
845 "compound" => "," );
846
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400847my %UnknownOperator;
848
849my %NodeType= (
850 "array_type" => "Array",
851 "binfo" => "Other",
852 "boolean_type" => "Intrinsic",
853 "complex_type" => "Intrinsic",
854 "const_decl" => "Other",
855 "enumeral_type" => "Enum",
856 "field_decl" => "Other",
857 "function_decl" => "Other",
858 "function_type" => "FunctionType",
859 "identifier_node" => "Other",
860 "integer_cst" => "Other",
861 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400862 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400863 "method_type" => "MethodType",
864 "namespace_decl" => "Other",
865 "parm_decl" => "Other",
866 "pointer_type" => "Pointer",
867 "real_cst" => "Other",
868 "real_type" => "Intrinsic",
869 "record_type" => "Struct",
870 "reference_type" => "Ref",
871 "string_cst" => "Other",
872 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400873 "template_type_parm" => "TemplateParam",
874 "typename_type" => "TypeName",
875 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400876 "tree_list" => "Other",
877 "tree_vec" => "Other",
878 "type_decl" => "Other",
879 "union_type" => "Union",
880 "var_decl" => "Other",
881 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400882 "nop_expr" => "Other", #
883 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400884 "offset_type" => "Other" );
885
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400886my %CppKeywords_C = map {$_=>1} (
887 # C++ 2003 keywords
888 "public",
889 "protected",
890 "private",
891 "default",
892 "template",
893 "new",
894 #"asm",
895 "dynamic_cast",
896 "auto",
897 "try",
898 "namespace",
899 "typename",
900 "using",
901 "reinterpret_cast",
902 "friend",
903 "class",
904 "virtual",
905 "const_cast",
906 "mutable",
907 "static_cast",
908 "export",
909 # C++0x keywords
910 "noexcept",
911 "nullptr",
912 "constexpr",
913 "static_assert",
914 "explicit",
915 # cannot be used as a macro name
916 # as it is an operator in C++
917 "and",
918 #"and_eq",
919 "not",
920 #"not_eq",
921 "or"
922 #"or_eq",
923 #"bitand",
924 #"bitor",
925 #"xor",
926 #"xor_eq",
927 #"compl"
928);
929
930my %CppKeywords_F = map {$_=>1} (
931 "delete",
932 "catch",
933 "alignof",
934 "thread_local",
935 "decltype",
936 "typeid"
937);
938
939my %CppKeywords_O = map {$_=>1} (
940 "bool",
941 "register",
942 "inline",
943 "operator"
944);
945
946my %CppKeywords_A = map {$_=>1} (
947 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400948 "throw",
949 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400950);
951
952foreach (keys(%CppKeywords_C),
953keys(%CppKeywords_F),
954keys(%CppKeywords_O)) {
955 $CppKeywords_A{$_}=1;
956}
957
958# Header file extensions as described by gcc
959my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
960
961my %IntrinsicMangling = (
962 "void" => "v",
963 "bool" => "b",
964 "wchar_t" => "w",
965 "char" => "c",
966 "signed char" => "a",
967 "unsigned char" => "h",
968 "short" => "s",
969 "unsigned short" => "t",
970 "int" => "i",
971 "unsigned int" => "j",
972 "long" => "l",
973 "unsigned long" => "m",
974 "long long" => "x",
975 "__int64" => "x",
976 "unsigned long long" => "y",
977 "__int128" => "n",
978 "unsigned __int128" => "o",
979 "float" => "f",
980 "double" => "d",
981 "long double" => "e",
982 "__float80" => "e",
983 "__float128" => "g",
984 "..." => "z"
985);
986
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400987my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
988
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400989my %StdcxxMangling = (
990 "3std"=>"St",
991 "3std9allocator"=>"Sa",
992 "3std12basic_string"=>"Sb",
993 "3std12basic_stringIcE"=>"Ss",
994 "3std13basic_istreamIcE"=>"Si",
995 "3std13basic_ostreamIcE"=>"So",
996 "3std14basic_iostreamIcE"=>"Sd"
997);
998
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +0400999my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001000my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1001
1002my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001003my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001004
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001005my %ConstantSuffix = (
1006 "unsigned int"=>"u",
1007 "long"=>"l",
1008 "unsigned long"=>"ul",
1009 "long long"=>"ll",
1010 "unsigned long long"=>"ull"
1011);
1012
1013my %ConstantSuffixR =
1014reverse(%ConstantSuffix);
1015
1016my %OperatorMangling = (
1017 "~" => "co",
1018 "=" => "aS",
1019 "|" => "or",
1020 "^" => "eo",
1021 "&" => "an",#ad (addr)
1022 "==" => "eq",
1023 "!" => "nt",
1024 "!=" => "ne",
1025 "<" => "lt",
1026 "<=" => "le",
1027 "<<" => "ls",
1028 "<<=" => "lS",
1029 ">" => "gt",
1030 ">=" => "ge",
1031 ">>" => "rs",
1032 ">>=" => "rS",
1033 "()" => "cl",
1034 "%" => "rm",
1035 "[]" => "ix",
1036 "&&" => "aa",
1037 "||" => "oo",
1038 "*" => "ml",#de (deref)
1039 "++" => "pp",#
1040 "--" => "mm",#
1041 "new" => "nw",
1042 "delete" => "dl",
1043 "new[]" => "na",
1044 "delete[]" => "da",
1045 "+=" => "pL",
1046 "+" => "pl",#ps (pos)
1047 "-" => "mi",#ng (neg)
1048 "-=" => "mI",
1049 "*=" => "mL",
1050 "/=" => "dV",
1051 "&=" => "aN",
1052 "|=" => "oR",
1053 "%=" => "rM",
1054 "^=" => "eO",
1055 "/" => "dv",
1056 "->*" => "pm",
1057 "->" => "pt",#rf (ref)
1058 "," => "cm",
1059 "?" => "qu",
1060 "." => "dt",
1061 "sizeof"=> "sz"#st
1062);
1063
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001064my %Intrinsic_Keywords = map {$_=>1} (
1065 "true",
1066 "false",
1067 "_Bool",
1068 "_Complex",
1069 "const",
1070 "int",
1071 "long",
1072 "void",
1073 "short",
1074 "float",
1075 "volatile",
1076 "restrict",
1077 "unsigned",
1078 "signed",
1079 "char",
1080 "double",
1081 "class",
1082 "struct",
1083 "union",
1084 "enum"
1085);
1086
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001087my %GlibcHeader = map {$_=>1} (
1088 "aliases.h",
1089 "argp.h",
1090 "argz.h",
1091 "assert.h",
1092 "cpio.h",
1093 "ctype.h",
1094 "dirent.h",
1095 "envz.h",
1096 "errno.h",
1097 "error.h",
1098 "execinfo.h",
1099 "fcntl.h",
1100 "fstab.h",
1101 "ftw.h",
1102 "glob.h",
1103 "grp.h",
1104 "iconv.h",
1105 "ifaddrs.h",
1106 "inttypes.h",
1107 "langinfo.h",
1108 "limits.h",
1109 "link.h",
1110 "locale.h",
1111 "malloc.h",
1112 "math.h",
1113 "mntent.h",
1114 "monetary.h",
1115 "nl_types.h",
1116 "obstack.h",
1117 "printf.h",
1118 "pwd.h",
1119 "regex.h",
1120 "sched.h",
1121 "search.h",
1122 "setjmp.h",
1123 "shadow.h",
1124 "signal.h",
1125 "spawn.h",
1126 "stdarg.h",
1127 "stdint.h",
1128 "stdio.h",
1129 "stdlib.h",
1130 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001131 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001132 "tar.h",
1133 "termios.h",
1134 "time.h",
1135 "ulimit.h",
1136 "unistd.h",
1137 "utime.h",
1138 "wchar.h",
1139 "wctype.h",
1140 "wordexp.h" );
1141
1142my %GlibcDir = map {$_=>1} (
1143 "arpa",
1144 "bits",
1145 "gnu",
1146 "netinet",
1147 "net",
1148 "nfs",
1149 "rpc",
1150 "sys",
1151 "linux" );
1152
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001153my %WinHeaders = map {$_=>1} (
1154 "dos.h",
1155 "process.h",
1156 "winsock.h",
1157 "config-win.h",
1158 "mem.h",
1159 "windows.h",
1160 "winsock2.h",
1161 "crtdbg.h",
1162 "ws2tcpip.h"
1163);
1164
1165my %ObsoleteHeaders = map {$_=>1} (
1166 "iostream.h",
1167 "fstream.h"
1168);
1169
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001170my %AlienHeaders = map {$_=>1} (
1171 # Solaris
1172 "thread.h",
1173 "sys/atomic.h",
1174 # HPUX
1175 "sys/stream.h",
1176 # Symbian
1177 "AknDoc.h",
1178 # Atari ST
1179 "ext.h",
1180 "tos.h",
1181 # MS-DOS
1182 "alloc.h",
1183 # Sparc
1184 "sys/atomic.h"
1185);
1186
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001187my %ConfHeaders = map {$_=>1} (
1188 "atomic",
1189 "conf.h",
1190 "config.h",
1191 "configure.h",
1192 "build.h",
1193 "setup.h"
1194);
1195
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001196my %LocalIncludes = map {$_=>1} (
1197 "/usr/local/include",
1198 "/usr/local" );
1199
1200my %OS_AddPath=(
1201# These paths are needed if the tool cannot detect them automatically
1202 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001203 "include"=>[
1204 "/Library",
1205 "/Developer/usr/include"
1206 ],
1207 "lib"=>[
1208 "/Library",
1209 "/Developer/usr/lib"
1210 ],
1211 "bin"=>[
1212 "/Developer/usr/bin"
1213 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001214 },
1215 "beos"=>{
1216 # Haiku has GCC 2.95.3 by default
1217 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001218 "include"=>[
1219 "/boot/common",
1220 "/boot/develop"
1221 ],
1222 "lib"=>[
1223 "/boot/common/lib",
1224 "/boot/system/lib",
1225 "/boot/apps"
1226 ],
1227 "bin"=>[
1228 "/boot/common/bin",
1229 "/boot/system/bin",
1230 "/boot/develop/abi"
1231 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001233);
1234
1235my %Slash_Type=(
1236 "default"=>"/",
1237 "windows"=>"\\"
1238);
1239
1240my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1241
1242# Global Variables
1243my %COMMON_LANGUAGE=(
1244 1 => "C",
1245 2 => "C" );
1246
1247my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001248my $MAX_CPPFILT_FILE_SIZE = 50000;
1249my $CPPFILT_SUPPORT_FILE;
1250
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001251my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1252
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001253my $STDCXX_TESTING = 0;
1254my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001255my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001256
1257my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
1258my $CheckObjectsOnly = $CheckObjectsOnly_Opt;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001259
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001260my $TargetComponent;
1261
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001262my $CheckUndefined = 0;
1263
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001264# Set Target Component Name
1265if($TargetComponent_Opt) {
1266 $TargetComponent = lc($TargetComponent_Opt);
1267}
1268else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001269{ # default: library
1270 # other components: header, system, ...
1271 $TargetComponent = "library";
1272}
1273
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001274my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001275
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001276my $SystemRoot;
1277
1278my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001279my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001280my %LOG_PATH;
1281my %DEBUG_PATH;
1282my %Cache;
1283my %LibInfo;
1284my $COMPILE_ERRORS = 0;
1285my %CompilerOptions;
1286my %CheckedDyLib;
1287my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1288
1289# Constants (#defines)
1290my %Constants;
1291my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001292my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001293
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001294# Extra Info
1295my %SymbolHeader;
1296my %KnownLibs;
1297
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001298# Templates
1299my %TemplateInstance;
1300my %BasicTemplate;
1301my %TemplateArg;
1302my %TemplateDecl;
1303my %TemplateMap;
1304
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001305# Types
1306my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001307my %SkipTypes = (
1308 "1"=>{},
1309 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001310my %CheckedTypes;
1311my %TName_Tid;
1312my %EnumMembName_Id;
1313my %NestedNameSpaces = (
1314 "1"=>{},
1315 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001316my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001317my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001318my %ClassVTable;
1319my %ClassVTable_Content;
1320my %VTableClass;
1321my %AllocableClass;
1322my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001323my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001324my %Class_SubClasses;
1325my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001326my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001327my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001328
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001329my %CheckedTypeInfo;
1330
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001331# Typedefs
1332my %Typedef_BaseName;
1333my %Typedef_Tr;
1334my %Typedef_Eq;
1335my %StdCxxTypedef;
1336my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001337my %MissedBase;
1338my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001339my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001340
1341# Symbols
1342my %SymbolInfo;
1343my %tr_name;
1344my %mangled_name_gcc;
1345my %mangled_name;
1346my %SkipSymbols = (
1347 "1"=>{},
1348 "2"=>{} );
1349my %SkipNameSpaces = (
1350 "1"=>{},
1351 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001352my %AddNameSpaces = (
1353 "1"=>{},
1354 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001355my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001356my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001357my %SymbolsList_App;
1358my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001359my %Symbol_Library = (
1360 "1"=>{},
1361 "2"=>{} );
1362my %Library_Symbol = (
1363 "1"=>{},
1364 "2"=>{} );
1365my %DepSymbol_Library = (
1366 "1"=>{},
1367 "2"=>{} );
1368my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001369 "1"=>{},
1370 "2"=>{} );
1371my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001372my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001373my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001374my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001375my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001376my %Library_Needed= (
1377 "1"=>{},
1378 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001379
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001380# Extra Info
1381my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001382my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001383
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001384# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001385my %Include_Preamble = (
1386 "1"=>[],
1387 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001388my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001389my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001390my %HeaderName_Paths;
1391my %Header_Dependency;
1392my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001393my %Include_Paths = (
1394 "1"=>[],
1395 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001396my %INC_PATH_AUTODETECT = (
1397 "1"=>1,
1398 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001399my %Add_Include_Paths = (
1400 "1"=>[],
1401 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001402my %Skip_Include_Paths;
1403my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001404my %Header_ErrorRedirect;
1405my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001406my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001407my %Header_ShouldNotBeUsed;
1408my %RecursiveIncludes;
1409my %Header_Include_Prefix;
1410my %SkipHeaders;
1411my %SkipHeadersList=(
1412 "1"=>{},
1413 "2"=>{} );
1414my %SkipLibs;
1415my %Include_Order;
1416my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001417my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001418my %TUnit_Funcs;
1419my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001420
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001421my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001422 "1"=>0,
1423 "2"=>0 );
1424my %AutoPreambleMode = (
1425 "1"=>0,
1426 "2"=>0 );
1427my %MinGWMode = (
1428 "1"=>0,
1429 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001430my %Cpp0xMode = (
1431 "1"=>0,
1432 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001433
1434# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001435my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001436my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001437my %RegisteredSONAMEs;
1438my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001439
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001440my %CheckedArch;
1441
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001442# System Objects
1443my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001444my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001445my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001446
1447# System Headers
1448my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001449my @DefaultCppPaths;
1450my @DefaultGccPaths;
1451my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001452my %DefaultCppHeader;
1453my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001454my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001455
1456# Merging
1457my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001458my $Version;
1459my %AddedInt;
1460my %RemovedInt;
1461my %AddedInt_Virt;
1462my %RemovedInt_Virt;
1463my %VirtualReplacement;
1464my %ChangedTypedef;
1465my %CompatRules;
1466my %IncompleteRules;
1467my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001468my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001469my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001470my %ReturnedClass;
1471my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001472my %SourceAlternative;
1473my %SourceAlternative_B;
1474my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001475my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001476
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001477# Calling Conventions
1478my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001479 1=>{ "R"=>0, "P"=>0 },
1480 2=>{ "R"=>0, "P"=>0 }
1481);
1482
1483# ABI Dump
1484my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001485
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001486# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001487my %TargetLibs;
1488my %TargetHeaders;
1489
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001490# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001491my $OStarget = $OSgroup;
1492my %TargetTools;
1493
1494# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001495my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001496
1497# Recursion locks
1498my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001499my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001500my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001501my @RecurInclude;
1502my @RecurConstant;
1503
1504# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001505my %SystemPaths = (
1506 "include"=>[],
1507 "lib"=>[],
1508 "bin"=>[]
1509);
1510my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001511my $GCC_PATH;
1512
1513# Symbols versioning
1514my %SymVer = (
1515 "1"=>{},
1516 "2"=>{} );
1517
1518# Problem descriptions
1519my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001520my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001521my %TotalAffected;
1522
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001523# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001524my $ContentID = 1;
1525my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1526my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1527my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1528my $ContentSpanEnd = "</span>\n";
1529my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1530my $ContentDivEnd = "</div>\n";
1531my $Content_Counter = 0;
1532
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001533# Modes
1534my $JoinReport = 1;
1535my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001536
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001537my %Severity_Val=(
1538 "High"=>3,
1539 "Medium"=>2,
1540 "Low"=>1,
1541 "Safe"=>-1
1542);
1543
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001544sub get_Modules()
1545{
1546 my $TOOL_DIR = get_dirname($0);
1547 if(not $TOOL_DIR)
1548 { # patch for MS Windows
1549 $TOOL_DIR = ".";
1550 }
1551 my @SEARCH_DIRS = (
1552 # tool's directory
1553 abs_path($TOOL_DIR),
1554 # relative path to modules
1555 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001556 # install path
1557 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001558 );
1559 foreach my $DIR (@SEARCH_DIRS)
1560 {
1561 if(not is_abs($DIR))
1562 { # relative path
1563 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1564 }
1565 if(-d $DIR."/modules") {
1566 return $DIR."/modules";
1567 }
1568 }
1569 exitStatus("Module_Error", "can't find modules");
1570}
1571
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001572my %LoadedModules = ();
1573
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001574sub loadModule($)
1575{
1576 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001577 if(defined $LoadedModules{$Name}) {
1578 return;
1579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001580 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1581 if(not -f $Path) {
1582 exitStatus("Module_Error", "can't access \'$Path\'");
1583 }
1584 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001585 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001586}
1587
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001588sub readModule($$)
1589{
1590 my ($Module, $Name) = @_;
1591 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1592 if(not -f $Path) {
1593 exitStatus("Module_Error", "can't access \'$Path\'");
1594 }
1595 return readFile($Path);
1596}
1597
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001598sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001599{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001600 my $Number = $_[0];
1601 if(not $Number) {
1602 $Number = 1;
1603 }
1604 else {
1605 $Number = int($Number)+1;
1606 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001607 if($Number>3) {
1608 return $Number."th";
1609 }
1610 elsif($Number==1) {
1611 return "1st";
1612 }
1613 elsif($Number==2) {
1614 return "2nd";
1615 }
1616 elsif($Number==3) {
1617 return "3rd";
1618 }
1619 else {
1620 return $Number;
1621 }
1622}
1623
1624sub search_Tools($)
1625{
1626 my $Name = $_[0];
1627 return "" if(not $Name);
1628 if(my @Paths = keys(%TargetTools))
1629 {
1630 foreach my $Path (@Paths)
1631 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001632 if(-f join_P($Path, $Name)) {
1633 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001634 }
1635 if($CrossPrefix)
1636 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001637 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001638 if(-f $Candidate) {
1639 return $Candidate;
1640 }
1641 }
1642 }
1643 }
1644 else {
1645 return "";
1646 }
1647}
1648
1649sub synch_Cmd($)
1650{
1651 my $Name = $_[0];
1652 if(not $GCC_PATH)
1653 { # GCC was not found yet
1654 return "";
1655 }
1656 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001657 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001658 return $Candidate;
1659 }
1660 return "";
1661}
1662
1663sub get_CmdPath($)
1664{
1665 my $Name = $_[0];
1666 return "" if(not $Name);
1667 if(defined $Cache{"get_CmdPath"}{$Name}) {
1668 return $Cache{"get_CmdPath"}{$Name};
1669 }
1670 my %BinUtils = map {$_=>1} (
1671 "c++filt",
1672 "objdump",
1673 "readelf"
1674 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001675 if($BinUtils{$Name} and $GCC_PATH)
1676 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001677 if(my $Dir = get_dirname($GCC_PATH)) {
1678 $TargetTools{$Dir}=1;
1679 }
1680 }
1681 my $Path = search_Tools($Name);
1682 if(not $Path and $OSgroup eq "windows") {
1683 $Path = search_Tools($Name.".exe");
1684 }
1685 if(not $Path and $BinUtils{$Name})
1686 {
1687 if($CrossPrefix)
1688 { # user-defined prefix
1689 $Path = search_Cmd($CrossPrefix."-".$Name);
1690 }
1691 }
1692 if(not $Path and $BinUtils{$Name})
1693 {
1694 if(my $Candidate = synch_Cmd($Name))
1695 { # synch with GCC
1696 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001697 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001698 if(-f $Candidate) {
1699 $Path = $Candidate;
1700 }
1701 }
1702 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001703 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001704 $Path = $Candidate;
1705 }
1706 }
1707 }
1708 if(not $Path) {
1709 $Path = search_Cmd($Name);
1710 }
1711 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001712 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001713 $Path=search_Cmd($Name.".exe");
1714 }
1715 if($Path=~/\s/) {
1716 $Path = "\"".$Path."\"";
1717 }
1718 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1719}
1720
1721sub search_Cmd($)
1722{
1723 my $Name = $_[0];
1724 return "" if(not $Name);
1725 if(defined $Cache{"search_Cmd"}{$Name}) {
1726 return $Cache{"search_Cmd"}{$Name};
1727 }
1728 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1729 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1730 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001731 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001732 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001733 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001734 if(-f $CmdPath)
1735 {
1736 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001737 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001738 }
1739 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1740 }
1741 }
1742 return ($Cache{"search_Cmd"}{$Name} = "");
1743}
1744
1745sub get_CmdPath_Default($)
1746{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001747 return "" if(not $_[0]);
1748 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1749 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001750 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001751 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1752}
1753
1754sub get_CmdPath_Default_I($)
1755{ # search in PATH
1756 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001757 if($Name=~/find/)
1758 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001759 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001760 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001761 }
1762 }
1763 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001764 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001765 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001766 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001767 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001768 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001769 if($OSgroup eq "windows")
1770 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001771 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001772 return $Name;
1773 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001774 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001775 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001776 {
1777 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001778 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001779 }
1780 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001781 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001782}
1783
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001784sub classifyPath($)
1785{
1786 my $Path = $_[0];
1787 if($Path=~/[\*\[]/)
1788 { # wildcard
1789 $Path=~s/\*/.*/g;
1790 $Path=~s/\\/\\\\/g;
1791 return ($Path, "Pattern");
1792 }
1793 elsif($Path=~/[\/\\]/)
1794 { # directory or relative path
1795 return (path_format($Path, $OSgroup), "Path");
1796 }
1797 else {
1798 return ($Path, "Name");
1799 }
1800}
1801
1802sub readDescriptor($$)
1803{
1804 my ($LibVersion, $Content) = @_;
1805 return if(not $LibVersion);
1806 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1807 if(not $Content) {
1808 exitStatus("Error", "$DName is empty");
1809 }
1810 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001811 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001812 }
1813 $Content=~s/\/\*(.|\n)+?\*\///g;
1814 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001815
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001816 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1817 if($TargetVersion{$LibVersion}) {
1818 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1819 }
1820 if(not $Descriptor{$LibVersion}{"Version"}) {
1821 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1822 }
1823 if($Content=~/{RELPATH}/)
1824 {
1825 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1826 $Content =~ s/{RELPATH}/$RelDir/g;
1827 }
1828 else
1829 {
1830 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1831 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1832 }
1833 }
1834
1835 if(not $CheckObjectsOnly_Opt)
1836 {
1837 my $DHeaders = parseTag(\$Content, "headers");
1838 if(not $DHeaders) {
1839 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1840 }
1841 elsif(lc($DHeaders) ne "none")
1842 { # append the descriptor headers list
1843 if($Descriptor{$LibVersion}{"Headers"})
1844 { # multiple descriptors
1845 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
1846 }
1847 else {
1848 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1849 }
1850 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1851 {
1852 if(not -e $Path) {
1853 exitStatus("Access_Error", "can't access \'$Path\'");
1854 }
1855 }
1856 }
1857 }
1858 if(not $CheckHeadersOnly_Opt)
1859 {
1860 my $DObjects = parseTag(\$Content, "libs");
1861 if(not $DObjects) {
1862 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1863 }
1864 elsif(lc($DObjects) ne "none")
1865 { # append the descriptor libraries list
1866 if($Descriptor{$LibVersion}{"Libs"})
1867 { # multiple descriptors
1868 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1869 }
1870 else {
1871 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1872 }
1873 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1874 {
1875 if(not -e $Path) {
1876 exitStatus("Access_Error", "can't access \'$Path\'");
1877 }
1878 }
1879 }
1880 }
1881 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1882 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001883 if(not -d $Path) {
1884 exitStatus("Access_Error", "can't access directory \'$Path\'");
1885 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001886 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001887 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001888 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001889 }
1890 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1891 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001892 if(not -d $Path) {
1893 exitStatus("Access_Error", "can't access directory \'$Path\'");
1894 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001895 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001896 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001897 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001898 }
1899 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1900 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001901 if(not -d $Path) {
1902 exitStatus("Access_Error", "can't access directory \'$Path\'");
1903 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001904 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001905 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001906 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001907 $TargetTools{$Path}=1;
1908 }
1909 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1910 $CrossPrefix = $Prefix;
1911 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001912 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001913 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1914 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001915 if(not -d $Path) {
1916 exitStatus("Access_Error", "can't access directory \'$Path\'");
1917 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001918 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001919 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001920 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001921 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001922 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001923 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1924 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001925 if(not -d $Path) {
1926 exitStatus("Access_Error", "can't access directory \'$Path\'");
1927 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001928 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001929 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001930 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001931 }
1932 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001933 { # skip some auto-generated include paths
1934 if(not is_abs($Path))
1935 {
1936 if(my $P = abs_path($Path)) {
1937 $Path = $P;
1938 }
1939 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001940 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001941 }
1942 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001943 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001944 my ($CPath, $Type) = classifyPath($Path);
1945 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001946 }
1947 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001948 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1949 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001950 if($Option!~/\A\-(Wl|l|L)/)
1951 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001952 $CompilerOptions{$LibVersion} .= " ".$Option;
1953 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001954 }
1955 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1956 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1957 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001958 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001959 my ($CPath, $Type) = classifyPath($Path);
1960 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001961 }
1962 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1963 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1964 {
1965 my ($CPath, $Type) = classifyPath($Path);
1966 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1967 }
1968 if(my $DDefines = parseTag(\$Content, "defines"))
1969 {
1970 if($Descriptor{$LibVersion}{"Defines"})
1971 { # multiple descriptors
1972 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1973 }
1974 else {
1975 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1976 }
1977 }
1978 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1979 {
1980 if($Order=~/\A(.+):(.+)\Z/) {
1981 $Include_Order{$LibVersion}{$1} = $2;
1982 }
1983 }
1984 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1985 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001986 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001987 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1988 }
1989 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
1990 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001991 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001992 $SkipSymbols{$LibVersion}{$Symbol} = 1;
1993 }
1994 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
1995 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
1996 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001997 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
1998 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
1999 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002000 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2001 $SkipConstants{$LibVersion}{$Constant} = 1;
2002 }
2003 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2004 {
2005 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002006 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002007 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2008 }
2009 else {
2010 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2011 }
2012 }
2013}
2014
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002015sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002016{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002017 my $CodeRef = shift(@_);
2018 my $Tag = shift(@_);
2019 if(not $Tag or not $CodeRef) {
2020 return undef;
2021 }
2022 my $Sp = 0;
2023 if(@_) {
2024 $Sp = shift(@_);
2025 }
2026 my $Start = index(${$CodeRef}, "<$Tag>");
2027 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002028 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002029 my $End = index(${$CodeRef}, "</$Tag>");
2030 if($End!=-1)
2031 {
2032 my $TS = length($Tag)+3;
2033 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2034 substr($Content, 0, $TS-1, ""); # cut start tag
2035 substr($Content, -$TS, $TS, ""); # cut end tag
2036 if(not $Sp)
2037 {
2038 $Content=~s/\A\s+//g;
2039 $Content=~s/\s+\Z//g;
2040 }
2041 if(substr($Content, 0, 1) ne "<") {
2042 $Content = xmlSpecChars_R($Content);
2043 }
2044 return $Content;
2045 }
2046 }
2047 return undef;
2048}
2049
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002050sub getInfo($)
2051{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002052 my $DumpPath = $_[0];
2053 return if(not $DumpPath or not -f $DumpPath);
2054
2055 readTUDump($DumpPath);
2056
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002057 # processing info
2058 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002059
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002060 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002061 setAnonTypedef_All();
2062 }
2063
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002064 getTypeInfo_All();
2065 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002066 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002067 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002068 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002069
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002070 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002071 %LibInfo = ();
2072 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002073 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002074 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002075 %TemplateDecl = ();
2076 %StdCxxTypedef = ();
2077 %MissedTypedef = ();
2078 %Typedef_Tr = ();
2079 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002080 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002081
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002082 # clean cache
2083 delete($Cache{"getTypeAttr"});
2084 delete($Cache{"getTypeDeclId"});
2085
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002086 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002087 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002088 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002089 }
2090 else
2091 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002092 if($BinaryOnly and not $ExtendedCheck)
2093 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002094 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002095 }
2096 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002097 remove_Unused($Version, "Extended");
2098 }
2099 }
2100
2101 if($CheckInfo)
2102 {
2103 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2104 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2105 }
2106
2107 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2108 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002109 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002110 }
2111
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002112 if($Debug) {
2113 # debugMangling($Version);
2114 }
2115}
2116
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002117sub readTUDump($)
2118{
2119 my $DumpPath = $_[0];
2120
2121 open(TU_DUMP, $DumpPath);
2122 local $/ = undef;
2123 my $Content = <TU_DUMP>;
2124 close(TU_DUMP);
2125
2126 unlink($DumpPath);
2127
2128 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002129 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002130
2131 # clean memory
2132 undef $Content;
2133
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002134 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002135
2136 foreach (0 .. $#Lines)
2137 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002138 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002139 { # get a number and attributes of a node
2140 next if(not $NodeType{$2});
2141 $LibInfo{$Version}{"info_type"}{$1}=$2;
2142 $LibInfo{$Version}{"info"}{$1}=$3;
2143 }
2144
2145 # clean memory
2146 delete($Lines[$_]);
2147 }
2148
2149 # clean memory
2150 undef @Lines;
2151}
2152
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002153sub simplifyConstants()
2154{
2155 foreach my $Constant (keys(%{$Constants{$Version}}))
2156 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002157 if(defined $Constants{$Version}{$Constant}{"Header"})
2158 {
2159 my $Value = $Constants{$Version}{$Constant}{"Value"};
2160 if(defined $EnumConstants{$Version}{$Value}) {
2161 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2162 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002163 }
2164 }
2165}
2166
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002167sub simplifyNames()
2168{
2169 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2170 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002171 if($Typedef_Eq{$Version}{$Base}) {
2172 next;
2173 }
2174 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2175 if($#Translations==0)
2176 {
2177 if(length($Translations[0])<=length($Base)) {
2178 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2179 }
2180 }
2181 else
2182 { # select most appropriate
2183 foreach my $Tr (@Translations)
2184 {
2185 if($Base=~/\A\Q$Tr\E/)
2186 {
2187 $Typedef_Eq{$Version}{$Base} = $Tr;
2188 last;
2189 }
2190 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002191 }
2192 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002193 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002194 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002195 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002196 if(not $TypeName) {
2197 next;
2198 }
2199 next if(index($TypeName,"<")==-1);# template instances only
2200 if($TypeName=~/>(::\w+)+\Z/)
2201 { # skip unused types
2202 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002203 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002204 foreach my $Base (sort {length($b)<=>length($a)}
2205 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002206 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002207 next if(not $Base);
2208 next if(index($TypeName,$Base)==-1);
2209 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002210 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002211 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002212 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2213 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2214 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002215 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002216 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2217 {
2218 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2219 {
2220 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2221 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002222 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002223 }
2224 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002225 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002226 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002227 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002228 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002229 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2230 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002231 }
2232}
2233
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002234sub setAnonTypedef_All()
2235{
2236 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2237 {
2238 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2239 {
2240 if(isAnon(getNameByInfo($InfoId))) {
2241 $TypedefToAnon{getTypeId($InfoId)} = 1;
2242 }
2243 }
2244 }
2245}
2246
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002247sub setTemplateParams_All()
2248{
2249 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2250 {
2251 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2252 setTemplateParams($_);
2253 }
2254 }
2255}
2256
2257sub setTemplateParams($)
2258{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002259 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002260 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002261 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002262 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002263 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002264 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002265 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002266 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002267 setTemplateInstParams($_[0], $TmplInst_Id);
2268 }
2269 }
2270
2271 $BasicTemplate{$Version}{$Tid} = $_[0];
2272
2273 if(my $Prms = getTreeAttr_Prms($_[0]))
2274 {
2275 if(my $Valu = getTreeAttr_Valu($Prms))
2276 {
2277 my $Vector = getTreeVec($Valu);
2278 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2279 {
2280 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2281 {
2282 if(my $Name = getNameByInfo($Val))
2283 {
2284 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2285 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2286 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2287 }
2288 else {
2289 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2290 }
2291 }
2292 }
2293 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002294 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002295 }
2296 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002297 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002298 {
2299 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2300 {
2301 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002302 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002303 }
2304 }
2305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002306}
2307
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002308sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002309{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002310 my ($Tmpl, $Inst) = @_;
2311
2312 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002313 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002314 my ($Params_InfoId, $ElemId) = ();
2315 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2316 $Params_InfoId = $1;
2317 }
2318 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2319 $ElemId = $1;
2320 }
2321 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002322 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002323 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2324 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2325 {
2326 my ($PPos, $PTypeId) = ($1, $2);
2327 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2328 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002329 if($PType eq "template_type_parm") {
2330 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002331 }
2332 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002333 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2334 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002335 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002336 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002337 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002338 else
2339 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002340 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002341 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002342 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002343 }
2344 }
2345 }
2346}
2347
2348sub getTypeDeclId($)
2349{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002350 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002351 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002352 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2353 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2354 }
2355 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2356 {
2357 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2358 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2359 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002360 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002361 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002362 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002363}
2364
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002365sub getTypeInfo_All()
2366{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002367 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002368 { # support for GCC < 4.5
2369 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2370 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2371 # FIXME: check GCC versions
2372 addMissedTypes_Pre();
2373 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002374
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002375 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002376 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002377 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2378 if($IType=~/_type\Z/ and $IType ne "function_type"
2379 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002380 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002381 }
2382 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002383
2384 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002385 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002386 "Name" => "...",
2387 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002388 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002389 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002390 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002391
2392 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002393 { # support for GCC < 4.5
2394 addMissedTypes_Post();
2395 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002396
2397 if($ADD_TMPL_INSTANCES)
2398 {
2399 # templates
2400 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2401 {
2402 if(defined $TemplateMap{$Version}{$Tid}
2403 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2404 {
2405 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2406 {
2407 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2408 {
2409 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2410 {
2411 if(my %MAttr = getTypeAttr($MembTypeId))
2412 {
2413 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2414 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2415 }
2416 }
2417 }
2418 }
2419 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2420 {
2421 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2422 {
2423 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2424
2425 if($NBid ne $Bid)
2426 {
2427 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2428 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2429 }
2430 }
2431 }
2432 }
2433 }
2434 }
2435}
2436
2437sub createType($$)
2438{
2439 my ($Attr, $LibVersion) = @_;
2440 my $NewId = ++$MAX_ID;
2441
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002442 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002443 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002444 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002445
2446 return "$NewId";
2447}
2448
2449sub instType($$$)
2450{ # create template instances
2451 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002452
2453 if(not $TypeInfo{$LibVersion}{$Tid}) {
2454 return undef;
2455 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002456 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2457
2458 foreach my $Key (sort keys(%{$Map}))
2459 {
2460 if(my $Val = $Map->{$Key})
2461 {
2462 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2463
2464 if(defined $Attr->{"NameSpace"}) {
2465 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2466 }
2467 foreach (keys(%{$Attr->{"TParam"}})) {
2468 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2469 }
2470 }
2471 else
2472 { # remove absent
2473 # _Traits, etc.
2474 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002475 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002476 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2477 }
2478 foreach (keys(%{$Attr->{"TParam"}}))
2479 {
2480 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2481 delete($Attr->{"TParam"}{$_});
2482 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002483 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002484 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2485 }
2486 }
2487 }
2488 }
2489
2490 my $Tmpl = 0;
2491
2492 if(defined $Attr->{"TParam"})
2493 {
2494 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2495 {
2496 my $PName = $Attr->{"TParam"}{$_}{"name"};
2497
2498 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2499 {
2500 my %Base = get_BaseType($PTid, $LibVersion);
2501
2502 if($Base{"Type"} eq "TemplateParam"
2503 or defined $Base{"Template"})
2504 {
2505 $Tmpl = 1;
2506 last
2507 }
2508 }
2509 }
2510 }
2511
2512 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2513 return "$Id";
2514 }
2515 else
2516 {
2517 if(not $Tmpl) {
2518 delete($Attr->{"Template"});
2519 }
2520
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002521 my $New = createType($Attr, $LibVersion);
2522
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002523 my %EMap = ();
2524 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2525 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2526 }
2527 foreach (keys(%{$Map})) {
2528 $EMap{$_} = $Map->{$_};
2529 }
2530
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002531 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2532 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002533 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002534 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002535 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002536 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002537 {
2538 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2539
2540 if($NBid ne $Bid)
2541 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002542 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2543 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002544 }
2545 }
2546 }
2547
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002548 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002549 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002550 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2551 {
2552 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2553 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2554 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002555 }
2556 }
2557
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002558 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002559 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002560 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2561 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002562 }
2563 }
2564
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002565 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2566 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002567 }
2568
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002569 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002570 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002571}
2572
2573sub addMissedTypes_Pre()
2574{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002575 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002576 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2577 { # detecting missed typedefs
2578 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2579 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002580 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002581 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002582 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002583 if($TypeType eq "Unknown")
2584 { # template_type_parm
2585 next;
2586 }
2587 my $TypeDeclId = getTypeDeclId($TypeId);
2588 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2589 my $TypedefName = getNameByInfo($MissedTDid);
2590 next if(not $TypedefName);
2591 next if($TypedefName eq "__float80");
2592 next if(isAnon($TypedefName));
2593 if(not $TypeDeclId
2594 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002595 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002596 }
2597 }
2598 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002599 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002600 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002601 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002602 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002603 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002604 next;
2605 }
2606 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002607 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002608 if(not $TypedefName) {
2609 next;
2610 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002611 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002612 my %MissedInfo = ( # typedef info
2613 "Name" => $TypedefName,
2614 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002615 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002616 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002617 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002618 my ($H, $L) = getLocation($MissedTDid);
2619 $MissedInfo{"Header"} = $H;
2620 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002621 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002622 { # other types
2623 next;
2624 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002625 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002626 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002627 next;
2628 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002629 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002630 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002631 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002632 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002633 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002634 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002635 next;
2636 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002637 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002638 next;
2639 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002640 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002641 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002642 next;
2643 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002644 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002645 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002646 next;
2647 }
2648 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002649
2650 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2651
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002652 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002653 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002654 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002655 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002656 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002657
2658 # add missed & remove other
2659 $TypeInfo{$Version} = \%AddTypes;
2660 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002661}
2662
2663sub addMissedTypes_Post()
2664{
2665 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2666 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002667 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2668 {
2669 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2670 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2671 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2672 }
2673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002674 }
2675}
2676
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002677sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002678{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002679 my $TypeId = $_[0];
2680 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2681 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002682 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002683 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002684 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002685}
2686
2687sub getArraySize($$)
2688{
2689 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002690 if(my $Size = getSize($TypeId))
2691 {
2692 my $Elems = $Size/$BYTE_SIZE;
2693 while($BaseName=~s/\s*\[(\d+)\]//) {
2694 $Elems/=$1;
2695 }
2696 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2697 {
2698 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2699 $Elems/=$BasicSize;
2700 }
2701 }
2702 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002703 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002704 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002705}
2706
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002707sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002708{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002709 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002710 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002711 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2712 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002713 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002714 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2715 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2716 if(not $NodeType)
2717 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002718 return ();
2719 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002720 if($NodeType eq "tree_vec")
2721 {
2722 if($Pos!=$#Positions)
2723 { # select last vector of parameters ( ns<P1>::type<P2> )
2724 next;
2725 }
2726 }
2727 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2728 foreach my $P (@Params)
2729 {
2730 if($P eq "") {
2731 return ();
2732 }
2733 elsif($P ne "\@skip\@") {
2734 @TmplParams = (@TmplParams, $P);
2735 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002736 }
2737 }
2738 return @TmplParams;
2739}
2740
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002741sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002742{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002743 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002744 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002745 if(defined $TypeInfo{$Version}{$TypeId}
2746 and $TypeInfo{$Version}{$TypeId}{"Name"})
2747 { # already created
2748 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002749 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002750 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2751 { # incomplete type
2752 return ();
2753 }
2754 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2755
2756 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002757 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002758
2759 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2760 {
2761 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2762 {
2763 if($Info=~/qual[ ]*:/)
2764 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002765 my $NewId = ++$MAX_ID;
2766
2767 $MissedBase{$Version}{$TypeId} = "$NewId";
2768 $MissedBase_R{$Version}{$NewId} = $TypeId;
2769 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2770 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002771 }
2772 }
2773 $TypeAttr{"Type"} = "Typedef";
2774 }
2775 else {
2776 $TypeAttr{"Type"} = getTypeType($TypeId);
2777 }
2778
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002779 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2780 {
2781 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2782 { # local code
2783 return ();
2784 }
2785 }
2786
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002787 if($TypeAttr{"Type"} eq "Unknown") {
2788 return ();
2789 }
2790 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2791 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002792 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002793 if(my $TName = $TypeAttr{"Name"})
2794 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002795 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002796 $TName_Tid{$Version}{$TName} = $TypeId;
2797 return %TypeAttr;
2798 }
2799 else {
2800 return ();
2801 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002802 }
2803 elsif($TypeAttr{"Type"} eq "Array")
2804 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002805 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2806 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002807 return ();
2808 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002809 if(my $Algn = getAlgn($TypeId)) {
2810 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2811 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002812 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002813 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002814 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002815 if(not $BTAttr{"Name"}) {
2816 return ();
2817 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002818 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002819 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002820 if(my $Size = getSize($TypeId)) {
2821 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2822 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002823 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002824 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2825 }
2826 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002827 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002828 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002829 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002830 else
2831 {
2832 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002833 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002834 $TypeAttr{"Name"} = $1."[]".$2;
2835 }
2836 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002837 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002838 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002839 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002840 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002841 if($BTAttr{"Header"}) {
2842 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002843 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002844 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002845 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2846 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002847 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002848 return ();
2849 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002850 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002851 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002852 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002853 if($TypeAttr{"Name"})
2854 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002855 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002856
2857 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2858 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002859 { # NOTE: register only one int: with built-in decl
2860 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2861 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2862 }
2863 }
2864 return %TypeAttr;
2865 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002866 else {
2867 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002869 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002870 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2871 {
2872 %TypeAttr = getTrivialTypeAttr($TypeId);
2873 if($TypeAttr{"Name"})
2874 {
2875 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2876 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2877 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2878 }
2879 return %TypeAttr;
2880 }
2881 else {
2882 return ();
2883 }
2884 }
2885 elsif($TypeAttr{"Type"} eq "SizeOf")
2886 {
2887 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2888 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2889 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2890 if($TypeAttr{"Name"})
2891 {
2892 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2893 return %TypeAttr;
2894 }
2895 else {
2896 return ();
2897 }
2898 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002899 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002900 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002901 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2902 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002903 return ();
2904 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002905 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002906 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002907 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002908 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002909 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002910 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002911 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002912 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002913 }
2914 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002915 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002916 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002917 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002918 return ();
2919 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002920 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002921 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002922 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002923 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002924 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002925 }
2926 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002927 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002928 {
2929 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002930 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002931 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002932 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002933 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2934 }
2935 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002936 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002937 }
2938 }
2939 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002940 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002941 }
2942 if($TypeAttr{"Type"} eq "Typedef")
2943 {
2944 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002945
2946 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2947 return ();
2948 }
2949
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002950 if(isAnon($TypeAttr{"Name"}))
2951 { # anon typedef to anon type: ._N
2952 return ();
2953 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002954
2955 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2956 { # artificial typedef of "struct X" to "X"
2957 $TypeAttr{"Artificial"} = 1;
2958 }
2959
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002960 if(my $NS = getNameSpace($TypeDeclId))
2961 {
2962 my $TypeName = $TypeAttr{"Name"};
2963 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2964 { # "some_type" is the typedef to "struct some_type" in C++
2965 if($3) {
2966 $TypeAttr{"Name"} = $3."::".$TypeName;
2967 }
2968 }
2969 else
2970 {
2971 $TypeAttr{"NameSpace"} = $NS;
2972 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002973
2974 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2975 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2976 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002977 if($BTAttr{"NameSpace"}
2978 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002979 { # types like "std::fpos<__mbstate_t>" are
2980 # not covered by typedefs in the TU dump
2981 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002982 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2983 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002984 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002985 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002986 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002987 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002988 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002989 }
2990 }
2991 }
2992 }
2993 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002994 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002995 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002996 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002997 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2998 { # typedef int*const TYPEDEF; // first
2999 # int foo(TYPEDEF p); // const is optimized out
3000 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3001 if($BTAttr{"Name"}=~/</)
3002 {
3003 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3004 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3005 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003006 }
3007 }
3008 }
3009 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3010 }
3011 if(not $TypeAttr{"Size"})
3012 {
3013 if($TypeAttr{"Type"} eq "Pointer") {
3014 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3015 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003016 elsif($BTAttr{"Size"}) {
3017 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003018 }
3019 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003020 if(my $Algn = getAlgn($TypeId)) {
3021 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3022 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003023 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003024 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3025 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003026 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003027 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003028 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003029 { # typedef to "class Class"
3030 # should not be registered in TName_Tid
3031 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3032 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3033 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003034 }
3035 return %TypeAttr;
3036 }
3037}
3038
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003039sub getTreeVec($)
3040{
3041 my %Vector = ();
3042 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3043 {
3044 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3045 { # string length is N-1 because of the null terminator
3046 $Vector{$1} = $2;
3047 }
3048 }
3049 return \%Vector;
3050}
3051
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003052sub get_TemplateParam($$)
3053{
3054 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003055 return () if(not $Type_Id);
3056 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3057 return () if(not $NodeType);
3058 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003059 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003060 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003061 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003062 my $Num = getNodeIntCst($Type_Id);
3063 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003064 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003065 }
3066 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003067 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003068 }
3069 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003070 elsif($NodeType eq "string_cst") {
3071 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003072 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003073 elsif($NodeType eq "tree_vec")
3074 {
3075 my $Vector = getTreeVec($Type_Id);
3076 my @Params = ();
3077 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3078 {
3079 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3080 push(@Params, $P2);
3081 }
3082 }
3083 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003084 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003085 elsif($NodeType eq "parm_decl")
3086 {
3087 (getNameByInfo($Type_Id));
3088 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003089 else
3090 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003091 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003092 my $PName = $ParamAttr{"Name"};
3093 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003094 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003095 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003096 if($PName=~/\>/)
3097 {
3098 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003099 $PName = $Cover;
3100 }
3101 }
3102 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003103 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003104 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3105 # template<typename _Key, typename _Compare = std::less<_Key>
3106 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3107 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3108 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3109 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003110 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003111 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003112 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003113 }
3114}
3115
3116sub cover_stdcxx_typedef($)
3117{
3118 my $TypeName = $_[0];
3119 if(my @Covers = sort {length($a)<=>length($b)}
3120 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3121 { # take the shortest typedef
3122 # FIXME: there may be more than
3123 # one typedefs to the same type
3124 return $Covers[0];
3125 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003126 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003127 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3128 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3129 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003130 if(my $Cover = $Covers[0])
3131 {
3132 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3133 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3134 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003135 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003136 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003137}
3138
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003139sub getNodeIntCst($)
3140{
3141 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003142 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003143 if($EnumMembName_Id{$Version}{$CstId}) {
3144 return $EnumMembName_Id{$Version}{$CstId};
3145 }
3146 elsif((my $Value = getTreeValue($CstId)) ne "")
3147 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003148 if($Value eq "0")
3149 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003150 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003151 return "false";
3152 }
3153 else {
3154 return "0";
3155 }
3156 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003157 elsif($Value eq "1")
3158 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003159 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003160 return "true";
3161 }
3162 else {
3163 return "1";
3164 }
3165 }
3166 else {
3167 return $Value;
3168 }
3169 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003170 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003171}
3172
3173sub getNodeStrCst($)
3174{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003175 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3176 {
3177 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003178 {
3179 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3180 { # string length is N-1 because of the null terminator
3181 return substr($1, 0, $2-1);
3182 }
3183 else
3184 { # identifier_node
3185 return substr($1, 0, $2);
3186 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003187 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003188 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003189 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003190}
3191
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003192sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003193{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003194 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003195 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3196 if($Type eq "FieldPtr") {
3197 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3198 }
3199 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3200 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003201 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003202 if($Type eq "MethodPtr")
3203 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003204 if(my $Size = getSize($TypeId))
3205 {
3206 $Size/=$BYTE_SIZE;
3207 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003208 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003209 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003210 if(my $Algn = getAlgn($TypeId)) {
3211 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003213 # Return
3214 if($Type eq "FieldPtr")
3215 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003216 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003217 if($ReturnAttr{"Name"}) {
3218 $MemPtrName .= $ReturnAttr{"Name"};
3219 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003220 $TypeAttr{"Return"} = $PtrId;
3221 }
3222 else
3223 {
3224 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3225 {
3226 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003227 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3228 if(not $ReturnAttr{"Name"})
3229 { # templates
3230 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003231 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003232 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003233 $TypeAttr{"Return"} = $ReturnTypeId;
3234 }
3235 }
3236 # Class
3237 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3238 {
3239 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003240 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003241 if($Class{"Name"}) {
3242 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3243 }
3244 else {
3245 $MemPtrName .= " (*)";
3246 }
3247 }
3248 else {
3249 $MemPtrName .= " (*)";
3250 }
3251 # Parameters
3252 if($Type eq "FuncPtr"
3253 or $Type eq "MethodPtr")
3254 {
3255 my @ParamTypeName = ();
3256 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3257 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003258 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003259 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003260 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003261 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003262 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3263 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003264 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003265 my $PTypeId = $1;
3266 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003267 if(not $ParamAttr{"Name"})
3268 { # templates (template_type_parm), etc.
3269 return ();
3270 }
3271 if($ParamAttr{"Name"} eq "void") {
3272 last;
3273 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003274 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003275 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003276 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003277 push(@ParamTypeName, $ParamAttr{"Name"});
3278 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003279 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3280 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003281 }
3282 else {
3283 last;
3284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003285 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003286 else {
3287 last;
3288 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003289 }
3290 }
3291 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3292 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003293 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003294 return %TypeAttr;
3295}
3296
3297sub getTreeTypeName($)
3298{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003299 my $TypeId = $_[0];
3300 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003301 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003302 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003303 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003304 if(my $Name = getNameByInfo($TypeId))
3305 { # bit_size_type
3306 return $Name;
3307 }
3308 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003309 return "unsigned int";
3310 }
3311 else {
3312 return "int";
3313 }
3314 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003315 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003316 return getNameByInfo($1);
3317 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003318 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003319 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003320}
3321
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003322sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003323{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003324 my $Ptd = pointTo($_[0]);
3325 return 0 if(not $Ptd);
3326 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003327 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003328 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3329 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003330 }
3331 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003332 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3333 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003334 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003335 if($InfoT1 eq "pointer_type"
3336 and $InfoT2 eq "function_type") {
3337 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003338 }
3339 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003340 return 0;
3341}
3342
3343sub isMethodPtr($)
3344{
3345 my $Ptd = pointTo($_[0]);
3346 return 0 if(not $Ptd);
3347 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3348 {
3349 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3350 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3351 and $Info=~/ ptrmem /) {
3352 return 1;
3353 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003354 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003355 return 0;
3356}
3357
3358sub isFieldPtr($)
3359{
3360 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3361 {
3362 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3363 and $Info=~/ ptrmem /) {
3364 return 1;
3365 }
3366 }
3367 return 0;
3368}
3369
3370sub pointTo($)
3371{
3372 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3373 {
3374 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3375 return $1;
3376 }
3377 }
3378 return "";
3379}
3380
3381sub getTypeTypeByTypeId($)
3382{
3383 my $TypeId = $_[0];
3384 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3385 {
3386 my $NType = $NodeType{$TType};
3387 if($NType eq "Intrinsic") {
3388 return $NType;
3389 }
3390 elsif(isFuncPtr($TypeId)) {
3391 return "FuncPtr";
3392 }
3393 elsif(isMethodPtr($TypeId)) {
3394 return "MethodPtr";
3395 }
3396 elsif(isFieldPtr($TypeId)) {
3397 return "FieldPtr";
3398 }
3399 elsif($NType ne "Other") {
3400 return $NType;
3401 }
3402 }
3403 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003404}
3405
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003406my %UnQual = (
3407 "r"=>"restrict",
3408 "v"=>"volatile",
3409 "c"=>"const",
3410 "cv"=>"const volatile"
3411);
3412
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003413sub getQual($)
3414{
3415 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003416 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3417 {
3418 my ($Qual, $To) = ();
3419 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3420 $Qual = $UnQual{$1};
3421 }
3422 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3423 $To = $1;
3424 }
3425 if($Qual and $To) {
3426 return ($Qual, $To);
3427 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003428 }
3429 return ();
3430}
3431
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003432sub getQualType($)
3433{
3434 if($_[0] eq "const volatile") {
3435 return "ConstVolatile";
3436 }
3437 return ucfirst($_[0]);
3438}
3439
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003440sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003441{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003442 my $TypeId = $_[0];
3443 my $TypeDeclId = getTypeDeclId($TypeId);
3444 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003445 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003446 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3447 return "Typedef";
3448 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003449 }
3450 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3451 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003452 if(($Qual or $To) and $TypeDeclId
3453 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003454 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003455 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003456 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003457 elsif(not $MissedBase_R{$Version}{$TypeId}
3458 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003459 return "Typedef";
3460 }
3461 elsif($Qual)
3462 { # qualified types
3463 return getQualType($Qual);
3464 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003465
3466 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3467 { # typedef struct { ... } name
3468 $TypeTypedef{$Version}{$TypeId} = $1;
3469 }
3470
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003471 my $TypeType = getTypeTypeByTypeId($TypeId);
3472 if($TypeType eq "Struct")
3473 {
3474 if($TypeDeclId
3475 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3476 return "Template";
3477 }
3478 }
3479 return $TypeType;
3480}
3481
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003482sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003483{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003484 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003485 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003486 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3487 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3488 return 0;
3489 }
3490 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3491 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003492 if(my $TDid = getTypeDeclId($_[0]))
3493 {
3494 if(getTypeId($TDid) eq $_[0]
3495 and getNameByInfo($TDid))
3496 {
3497 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3498 return $1;
3499 }
3500 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003501 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003502 }
3503 }
3504 return 0;
3505}
3506
3507sub selectBaseType($)
3508{
3509 my $TypeId = $_[0];
3510 if(defined $MissedTypedef{$Version}{$TypeId})
3511 { # add missed typedefs
3512 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3513 return ($TypeId, "");
3514 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003515 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003516 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3517 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003518
3519 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3520 my $MB = $MissedBase{$Version}{$TypeId};
3521
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003522 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003523 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003524 and (getTypeId($1) ne $TypeId)
3525 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003526 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003527 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003528 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003529 elsif($MB)
3530 { # add base
3531 return ($MB, "");
3532 }
3533 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003534 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003535 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003536 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003537 elsif($Qual or $To)
3538 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003539 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003540 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003541 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003542 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003543 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003544 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003545 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003546 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003547 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003548 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003549 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003550 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003551 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003552 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003553 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003554 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003555 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003556 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003557 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003558 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003559
3560 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003561}
3562
3563sub getSymbolInfo_All()
3564{
3565 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3566 { # reverse order
3567 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003568 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003569 }
3570 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003571
3572 if($ADD_TMPL_INSTANCES)
3573 {
3574 # templates
3575 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3576 {
3577 my %Map = ();
3578
3579 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3580 {
3581 if(defined $TemplateMap{$Version}{$ClassId})
3582 {
3583 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3584 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3585 }
3586 }
3587 }
3588
3589 if(defined $TemplateMap{$Version}{$Sid})
3590 {
3591 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3592 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3593 }
3594 }
3595
3596 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3597 {
3598 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3599 {
3600 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3601 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3602 }
3603 }
3604 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3605 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3606 }
3607 }
3608 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003609}
3610
3611sub getVarInfo_All()
3612{
3613 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3614 { # reverse order
3615 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003616 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003617 }
3618 }
3619}
3620
3621sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003622 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003623}
3624
3625sub getVarInfo($)
3626{
3627 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003628 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003629 {
3630 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3631 if($NSInfoType and $NSInfoType eq "function_decl") {
3632 return;
3633 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003634 }
3635 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3636 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3637 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3638 delete($SymbolInfo{$Version}{$InfoId});
3639 return;
3640 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003641 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003642 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003643 delete($SymbolInfo{$Version}{$InfoId});
3644 return;
3645 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003646 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3647 delete($SymbolInfo{$Version}{$InfoId});
3648 return;
3649 }
3650 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003651 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3652 {
3653 if($OSgroup eq "windows")
3654 { # cut the offset
3655 $MnglName=~s/\@\d+\Z//g;
3656 }
3657 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3658 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003659 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003660 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003661 { # validate mangled name
3662 delete($SymbolInfo{$Version}{$InfoId});
3663 return;
3664 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003665 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003666 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003667 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003668 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003669 }
3670 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3671 { # non-public global data
3672 delete($SymbolInfo{$Version}{$InfoId});
3673 return;
3674 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003675 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003676 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003677 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003678 if(not defined $TypeInfo{$Version}{$Rid}
3679 or not $TypeInfo{$Version}{$Rid}{"Name"})
3680 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003681 delete($SymbolInfo{$Version}{$InfoId});
3682 return;
3683 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003684 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3685 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003686 if(defined $Val) {
3687 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003689 }
3690 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003691 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3692 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003693 if(not defined $TypeInfo{$Version}{$ClassId}
3694 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3695 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003696 delete($SymbolInfo{$Version}{$InfoId});
3697 return;
3698 }
3699 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003700 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3701 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003702 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003703 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003704 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003705 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003706 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003707 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003708 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003709 if(not $CheckHeadersOnly)
3710 {
3711 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3712 {
3713 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3714 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3715 {
3716 if(link_symbol($ShortName, $Version, "-Deps"))
3717 { # "const" global data is mangled as _ZL... in the TU dump
3718 # but not mangled when compiling a C shared library
3719 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3720 }
3721 }
3722 }
3723 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003724 if($COMMON_LANGUAGE{$Version} eq "C++")
3725 {
3726 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3727 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003728 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003729 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3730 }
3731 }
3732 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3733 { # try to mangle symbol (link with libraries)
3734 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3735 }
3736 if($OStarget eq "windows")
3737 {
3738 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3739 { # link MS C++ symbols from library with GCC symbols from headers
3740 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3741 }
3742 }
3743 }
3744 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3745 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3746 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003747 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3748 {
3749 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3750 { # non-target symbols
3751 delete($SymbolInfo{$Version}{$InfoId});
3752 return;
3753 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003754 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003755 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3756 {
3757 if(defined $MissedTypedef{$Version}{$Rid})
3758 {
3759 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3760 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3761 }
3762 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003763 }
3764 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003765 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003766 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3767 }
3768 if($ShortName=~/\A(_Z|\?)/) {
3769 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3770 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003771
3772 if($ExtraDump) {
3773 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003775}
3776
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003777sub isConstType($$)
3778{
3779 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003780 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003781 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003782 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003783 }
3784 return ($Base{"Type"} eq "Const");
3785}
3786
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003787sub getTrivialName($$)
3788{
3789 my ($TypeInfoId, $TypeId) = @_;
3790 my %TypeAttr = ();
3791 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3792 if(not $TypeAttr{"Name"}) {
3793 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3794 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003795 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003796 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003797 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003798 if(isAnon($TypeAttr{"Name"}))
3799 {
3800 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003801 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003802 { # searching for a first not anon scope
3803 if($NSId eq $NameSpaceId) {
3804 last;
3805 }
3806 else
3807 {
3808 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3809 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003810 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003811 last;
3812 }
3813 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003814 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003815 }
3816 }
3817 else
3818 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003819 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003820 {
3821 if($NameSpaceId ne $TypeId) {
3822 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3823 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003824 }
3825 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003826 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003827 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3828 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003829 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003830 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003831 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003832 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003833 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003834 if($TypeAttr{"NameSpace"}) {
3835 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3836 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003837 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003838 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3839 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003840 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003841 if(my @TParams = getTParams($TypeId, "Type")) {
3842 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3843 }
3844 else {
3845 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3846 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003847 }
3848 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3849}
3850
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003851sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003852{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003853 my $TypeId = $_[0];
3854 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003855
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003856 my %TypeAttr = ();
3857
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003858 if($TemplateDecl{$Version}{$TypeId})
3859 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003860 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003861 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003862
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003863 setTypeAccess($TypeId, \%TypeAttr);
3864 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3865 if(isBuiltIn($TypeAttr{"Header"}))
3866 {
3867 delete($TypeAttr{"Header"});
3868 delete($TypeAttr{"Line"});
3869 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003870
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003871 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003872 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3873 if(not $TypeAttr{"Name"}) {
3874 return ();
3875 }
3876 if(not $TypeAttr{"NameSpace"}) {
3877 delete($TypeAttr{"NameSpace"});
3878 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003879
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003880 if($TypeAttr{"Type"} eq "Intrinsic")
3881 {
3882 if(defined $TypeAttr{"Header"})
3883 {
3884 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3885 { # support for SUSE 11.2
3886 # integer_type has srcp dump{1-2}.i
3887 delete($TypeAttr{"Header"});
3888 }
3889 }
3890 }
3891
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003892 my $Tmpl = undef;
3893
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003894 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003895 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003896 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3897
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003898 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003899 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003900 foreach my $Pos (0 .. $#TParams)
3901 {
3902 my $Val = $TParams[$Pos];
3903 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3904
3905 if(not defined $TypeAttr{"Template"})
3906 {
3907 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3908
3909 if($Base{"Type"} eq "TemplateParam"
3910 or defined $Base{"Template"}) {
3911 $TypeAttr{"Template"} = 1;
3912 }
3913 }
3914
3915 if($Tmpl)
3916 {
3917 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3918 {
3919 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3920
3921 if($Val eq $Arg) {
3922 $TypeAttr{"Template"} = 1;
3923 }
3924 }
3925 }
3926 }
3927
3928 if($Tmpl)
3929 {
3930 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3931 {
3932 if($Pos>$#TParams)
3933 {
3934 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3935 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3936 }
3937 }
3938 }
3939 }
3940
3941 if($ADD_TMPL_INSTANCES)
3942 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003943 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003944 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003945 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003946 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003947 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003948 {
3949 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3950 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3951 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003952 }
3953 if(not getTreeAttr_Binf($TypeId))
3954 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003955 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3956 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3957 }
3958 }
3959 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003960 }
3961 }
3962 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003963
3964 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3965
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003966 if(my $Size = getSize($TypeId))
3967 {
3968 $Size = $Size/$BYTE_SIZE;
3969 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003970 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003971 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003972 {
3973 if($ExtraDump)
3974 {
3975 if(not defined $TypeAttr{"Memb"}
3976 and not $Tmpl)
3977 { # declaration only
3978 $TypeAttr{"Forward"} = 1;
3979 }
3980 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003981 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003982
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003983 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003984 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003985 {
3986 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003987 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003988 }
3989 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003990 or $TypeAttr{"Type"} eq "Class")
3991 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003992 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003993 if($Skip) {
3994 return ();
3995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003996 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003997 if(my $Algn = getAlgn($TypeId)) {
3998 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3999 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004000 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004001
4002 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4003 {
4004 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004005 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004006 {
4007 if(not isAnon($TypeAttr{"Name"})) {
4008 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4009 }
4010 }
4011 }
4012
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004013 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004014 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4015 {
4016 my @Entries = split(/\n/, $VTable);
4017 foreach (1 .. $#Entries)
4018 {
4019 my $Entry = $Entries[$_];
4020 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004021 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004022 }
4023 }
4024 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004025
4026 if($TypeAttr{"Type"} eq "Enum")
4027 {
4028 if(not $TypeAttr{"NameSpace"})
4029 {
4030 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4031 {
4032 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004033 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004034 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004035 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004036 "Header"=>$TypeAttr{"Header"}
4037 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004038 if(isAnon($TypeAttr{"Name"}))
4039 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004040 if($ExtraDump
4041 or is_target_header($TypeAttr{"Header"}, $Version))
4042 {
4043 %{$Constants{$Version}{$MName}} = (
4044 "Value" => $MVal,
4045 "Header" => $TypeAttr{"Header"}
4046 );
4047 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004048 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004049 }
4050 }
4051 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004052 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004053 {
4054 if(defined $TypedefToAnon{$TypeId}) {
4055 $TypeAttr{"AnonTypedef"} = 1;
4056 }
4057 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004058
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004059 return %TypeAttr;
4060}
4061
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004062sub simplifyVTable($)
4063{
4064 my $Content = $_[0];
4065 if($Content=~s/ \[with (.+)]//)
4066 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4067 if(my @Elems = separate_Params($1, 0, 0))
4068 {
4069 foreach my $Elem (@Elems)
4070 {
4071 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4072 {
4073 my ($Arg, $Val) = ($1, $2);
4074
4075 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4076 $Content=~s/,\s*$Arg\b//g;
4077 }
4078 else {
4079 $Content=~s/\b$Arg\b/$Val/g;
4080 }
4081 }
4082 }
4083 }
4084 }
4085
4086 return $Content;
4087}
4088
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004089sub detect_lang($)
4090{
4091 my $TypeId = $_[0];
4092 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004093 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004094 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004095 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4096 }
4097 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004098 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004099 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004100 while($Fncs)
4101 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004102 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004103 return 1;
4104 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004105 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004106 }
4107 }
4108 return 0;
4109}
4110
4111sub setSpec($$)
4112{
4113 my ($TypeId, $TypeAttr) = @_;
4114 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4115 if($Info=~/\s+spec\s+/) {
4116 $TypeAttr->{"Spec"} = 1;
4117 }
4118}
4119
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004120sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004121{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004122 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004123 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004124 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004125 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004126 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004127 my $Pos = 0;
4128 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4129 {
4130 my ($Access, $BInfoId) = ($1, $2);
4131 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004132
4133 if($ClassId==$TypeId)
4134 { # class A<N>:public A<N-1>
4135 next;
4136 }
4137
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004138 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4139 if(not $CType or $CType eq "template_type_parm"
4140 or $CType eq "typename_type")
4141 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004142 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004143 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004144 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004145 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004146 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4147 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004148 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004149 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4150 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004151 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004152 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004153 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004154 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4155 }
4156 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004157 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004158 }
4159 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004160 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004161}
4162
4163sub getBinfClassId($)
4164{
4165 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4166 $Info=~/type[ ]*:[ ]*@(\d+) /;
4167 return $1;
4168}
4169
4170sub unmangledFormat($$)
4171{
4172 my ($Name, $LibVersion) = @_;
4173 $Name = uncover_typedefs($Name, $LibVersion);
4174 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4175 $Name=~s/\(\w+\)(\d)/$1/;
4176 return $Name;
4177}
4178
4179sub modelUnmangled($$)
4180{
4181 my ($InfoId, $Compiler) = @_;
4182 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4183 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4184 }
4185 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4186 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4187 $PureSignature = "~".$PureSignature;
4188 }
4189 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4190 {
4191 my (@Params, @ParamTypes) = ();
4192 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4193 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4194 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4195 }
4196 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4197 { # checking parameters
4198 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004199 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004200 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004201 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004202
4203 if($PName eq "this"
4204 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4205 {
4206 next;
4207 }
4208
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004209 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004210 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004211 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004212 }
4213 @ParamTypes = (@ParamTypes, $PTName);
4214 }
4215 if(@ParamTypes) {
4216 $PureSignature .= "(".join(", ", @ParamTypes).")";
4217 }
4218 else
4219 {
4220 if($Compiler eq "MSVC")
4221 {
4222 $PureSignature .= "(void)";
4223 }
4224 else
4225 { # GCC
4226 $PureSignature .= "()";
4227 }
4228 }
4229 $PureSignature = delete_keywords($PureSignature);
4230 }
4231 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4232 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004233 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004234 $PureSignature = $ClassName."::".$PureSignature;
4235 }
4236 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4237 $PureSignature = $NS."::".$PureSignature;
4238 }
4239 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4240 $PureSignature .= " const";
4241 }
4242 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4243 $PureSignature .= " volatile";
4244 }
4245 my $ShowReturn = 0;
4246 if($Compiler eq "MSVC"
4247 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4248 {
4249 $ShowReturn=1;
4250 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004251 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4252 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004253 {
4254 $ShowReturn=1;
4255 }
4256 if($ShowReturn)
4257 { # mangled names for template function specializations include return value
4258 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4259 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004260 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004261 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4262 $PureSignature = $ReturnName." ".$PureSignature;
4263 }
4264 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004265 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004266}
4267
4268sub mangle_symbol($$$)
4269{ # mangling for simple methods
4270 # see gcc-4.6.0/gcc/cp/mangle.c
4271 my ($InfoId, $LibVersion, $Compiler) = @_;
4272 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4273 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4274 }
4275 my $Mangled = "";
4276 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004277 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004278 }
4279 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004280 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004281 }
4282 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4283}
4284
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004285sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004286{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004287 my ($InfoId, $LibVersion) = @_;
4288 return "";
4289}
4290
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004291sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004292{ # see gcc-4.6.0/gcc/cp/mangle.c
4293 my ($InfoId, $LibVersion) = @_;
4294 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004295 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004296 my %Repl = ();# SN_ replacements
4297 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4298 {
4299 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4300 if($MangledClass!~/\AN/) {
4301 $MangledClass = "N".$MangledClass;
4302 }
4303 else {
4304 $MangledClass=~s/E\Z//;
4305 }
4306 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4307 $MangledClass=~s/\AN/NV/;
4308 }
4309 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4310 $MangledClass=~s/\AN/NK/;
4311 }
4312 $Mangled .= $MangledClass;
4313 }
4314 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4315 { # mangled by name due to the absence of structured info
4316 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4317 if($MangledNS!~/\AN/) {
4318 $MangledNS = "N".$MangledNS;
4319 }
4320 else {
4321 $MangledNS=~s/E\Z//;
4322 }
4323 $Mangled .= $MangledNS;
4324 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004325 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004326 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004327 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004328 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004329 foreach (@TPos) {
4330 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4331 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004332 }
4333 elsif($TmplParams)
4334 { # remangling mode
4335 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004336 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004337 }
4338 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4339 $Mangled .= "C1";
4340 }
4341 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4342 $Mangled .= "D0";
4343 }
4344 elsif($ShortName)
4345 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004346 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4347 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004348 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004349 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004350 { # "const" global data is mangled as _ZL...
4351 $Mangled .= "L";
4352 }
4353 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004354 if($ShortName=~/\Aoperator(\W.*)\Z/)
4355 {
4356 my $Op = $1;
4357 $Op=~s/\A[ ]+//g;
4358 if(my $OpMngl = $OperatorMangling{$Op}) {
4359 $Mangled .= $OpMngl;
4360 }
4361 else { # conversion operator
4362 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4363 }
4364 }
4365 else {
4366 $Mangled .= length($ShortName).$ShortName;
4367 }
4368 if(@TParams)
4369 { # templates
4370 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004371 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004372 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4373 }
4374 $Mangled .= "E";
4375 }
4376 if(not $ClassId and @TParams) {
4377 add_substitution($ShortName, \%Repl, 0);
4378 }
4379 }
4380 if($ClassId or $NameSpace) {
4381 $Mangled .= "E";
4382 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004383 if(@TParams)
4384 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004385 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004386 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4387 }
4388 }
4389 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4390 {
4391 my @Params = ();
4392 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4393 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4394 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4395 }
4396 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4397 { # checking parameters
4398 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4399 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4400 }
4401 if(not @Params) {
4402 $Mangled .= "v";
4403 }
4404 }
4405 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4406 $Mangled = write_stdcxx_substitution($Mangled);
4407 if($Mangled eq "_Z") {
4408 return "";
4409 }
4410 return $Mangled;
4411}
4412
4413sub correct_incharge($$$)
4414{
4415 my ($InfoId, $LibVersion, $Mangled) = @_;
4416 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4417 {
4418 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004419 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004420 }
4421 }
4422 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4423 {
4424 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004425 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004426 }
4427 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004428 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004429 }
4430 }
4431 return $Mangled;
4432}
4433
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004434sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004435{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004436 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004437 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004438 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004439 return $Name;
4440 }
4441 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004442 while(my $CPos = find_center($TParams, "<"))
4443 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004444 $TParams = substr($TParams, $CPos);
4445 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004446 if($TParams=~s/\A<(.+)>\Z/$1/) {
4447 $Name=~s/<\Q$TParams\E>\Z//;
4448 }
4449 else
4450 { # error
4451 $TParams = "";
4452 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004453 return ($Name, $TParams);
4454}
4455
4456sub get_sub_ns($)
4457{
4458 my $Name = $_[0];
4459 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004460 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004461 {
4462 push(@NS, substr($Name, 0, $CPos));
4463 $Name = substr($Name, $CPos);
4464 $Name=~s/\A:://;
4465 }
4466 return (join("::", @NS), $Name);
4467}
4468
4469sub mangle_ns($$$)
4470{
4471 my ($Name, $LibVersion, $Repl) = @_;
4472 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4473 {
4474 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4475 $Mangled=~s/\AN(.+)E\Z/$1/;
4476 return $Mangled;
4477
4478 }
4479 else
4480 {
4481 my ($MangledNS, $SubNS) = ("", "");
4482 ($SubNS, $Name) = get_sub_ns($Name);
4483 if($SubNS) {
4484 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4485 }
4486 $MangledNS .= length($Name).$Name;
4487 add_substitution($MangledNS, $Repl, 0);
4488 return $MangledNS;
4489 }
4490}
4491
4492sub mangle_param($$$)
4493{
4494 my ($PTid, $LibVersion, $Repl) = @_;
4495 my ($MPrefix, $Mangled) = ("", "");
4496 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004497 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004498 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004499 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004500 if(not $BaseType_Name) {
4501 return "";
4502 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004503 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004504 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004505 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4506 while($Suffix=~/(&|\*|const)\Z/)
4507 {
4508 if($Suffix=~s/[ ]*&\Z//) {
4509 $MPrefix .= "R";
4510 }
4511 if($Suffix=~s/[ ]*\*\Z//) {
4512 $MPrefix .= "P";
4513 }
4514 if($Suffix=~s/[ ]*const\Z//)
4515 {
4516 if($MPrefix=~/R|P/
4517 or $Suffix=~/&|\*/) {
4518 $MPrefix .= "K";
4519 }
4520 }
4521 if($Suffix=~s/[ ]*volatile\Z//) {
4522 $MPrefix .= "V";
4523 }
4524 #if($Suffix=~s/[ ]*restrict\Z//) {
4525 #$MPrefix .= "r";
4526 #}
4527 }
4528 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4529 $Mangled .= $Token;
4530 }
4531 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4532 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004533 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004534 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004535 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004536 foreach (@TPos) {
4537 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4538 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004539 }
4540 elsif($TmplParams)
4541 { # remangling mode
4542 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004543 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004544 }
4545 my $MangledNS = "";
4546 my ($SubNS, $SName) = get_sub_ns($ShortName);
4547 if($SubNS) {
4548 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4549 }
4550 $MangledNS .= length($SName).$SName;
4551 if(@TParams) {
4552 add_substitution($MangledNS, $Repl, 0);
4553 }
4554 $Mangled .= "N".$MangledNS;
4555 if(@TParams)
4556 { # templates
4557 $Mangled .= "I";
4558 foreach my $TParam (@TParams) {
4559 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4560 }
4561 $Mangled .= "E";
4562 }
4563 $Mangled .= "E";
4564 }
4565 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4566 {
4567 if($BaseType{"Type"} eq "MethodPtr") {
4568 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4569 }
4570 else {
4571 $Mangled .= "PF";
4572 }
4573 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4574 my @Params = keys(%{$BaseType{"Param"}});
4575 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4576 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4577 }
4578 if(not @Params) {
4579 $Mangled .= "v";
4580 }
4581 $Mangled .= "E";
4582 }
4583 elsif($BaseType{"Type"} eq "FieldPtr")
4584 {
4585 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4586 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4587 }
4588 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4589 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4590 {
4591 if($Mangled eq $Optimized)
4592 {
4593 if($ShortName!~/::/)
4594 { # remove "N ... E"
4595 if($MPrefix) {
4596 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4597 }
4598 else {
4599 $Mangled=~s/\AN(.+)E\Z/$1/g;
4600 }
4601 }
4602 }
4603 else {
4604 $Mangled = $Optimized;
4605 }
4606 }
4607 add_substitution($Mangled, $Repl, 1);
4608 return $Mangled;
4609}
4610
4611sub mangle_template_param($$$)
4612{ # types + literals
4613 my ($TParam, $LibVersion, $Repl) = @_;
4614 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4615 return mangle_param($TPTid, $LibVersion, $Repl);
4616 }
4617 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4618 { # class_name<1u>::method(...)
4619 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4620 }
4621 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4622 { # class_name<(signed char)1>::method(...)
4623 return "L".$IntrinsicMangling{$1}.$2."E";
4624 }
4625 elsif($TParam eq "true")
4626 { # class_name<true>::method(...)
4627 return "Lb1E";
4628 }
4629 elsif($TParam eq "false")
4630 { # class_name<true>::method(...)
4631 return "Lb0E";
4632 }
4633 else { # internal error
4634 return length($TParam).$TParam;
4635 }
4636}
4637
4638sub add_substitution($$$)
4639{
4640 my ($Value, $Repl, $Rec) = @_;
4641 if($Rec)
4642 { # subtypes
4643 my @Subs = ($Value);
4644 while($Value=~s/\A(R|P|K)//) {
4645 push(@Subs, $Value);
4646 }
4647 foreach (reverse(@Subs)) {
4648 add_substitution($_, $Repl, 0);
4649 }
4650 return;
4651 }
4652 return if($Value=~/\AS(\d*)_\Z/);
4653 $Value=~s/\AN(.+)E\Z/$1/g;
4654 return if(defined $Repl->{$Value});
4655 return if(length($Value)<=1);
4656 return if($StdcxxMangling{$Value});
4657 # check for duplicates
4658 my $Base = $Value;
4659 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4660 {
4661 my $Num = $Repl->{$Type};
4662 my $Replace = macro_mangle($Num);
4663 $Base=~s/\Q$Replace\E/$Type/;
4664 }
4665 if(my $OldNum = $Repl->{$Base})
4666 {
4667 $Repl->{$Value} = $OldNum;
4668 return;
4669 }
4670 my @Repls = sort {$b<=>$a} values(%{$Repl});
4671 if(@Repls) {
4672 $Repl->{$Value} = $Repls[0]+1;
4673 }
4674 else {
4675 $Repl->{$Value} = -1;
4676 }
4677 # register duplicates
4678 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004679 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004680 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4681 {
4682 next if($Base eq $Type);
4683 my $Num = $Repl->{$Type};
4684 my $Replace = macro_mangle($Num);
4685 $Base=~s/\Q$Type\E/$Replace/;
4686 $Repl->{$Base} = $Repl->{$Value};
4687 }
4688}
4689
4690sub macro_mangle($)
4691{
4692 my $Num = $_[0];
4693 if($Num==-1) {
4694 return "S_";
4695 }
4696 else
4697 {
4698 my $Code = "";
4699 if($Num<10)
4700 { # S0_, S1_, S2_, ...
4701 $Code = $Num;
4702 }
4703 elsif($Num>=10 and $Num<=35)
4704 { # SA_, SB_, SC_, ...
4705 $Code = chr(55+$Num);
4706 }
4707 else
4708 { # S10_, S11_, S12_
4709 $Code = $Num-26; # 26 is length of english alphabet
4710 }
4711 return "S".$Code."_";
4712 }
4713}
4714
4715sub write_stdcxx_substitution($)
4716{
4717 my $Mangled = $_[0];
4718 if($StdcxxMangling{$Mangled}) {
4719 return $StdcxxMangling{$Mangled};
4720 }
4721 else
4722 {
4723 my @Repls = keys(%StdcxxMangling);
4724 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4725 foreach my $MangledType (@Repls)
4726 {
4727 my $Replace = $StdcxxMangling{$MangledType};
4728 #if($Mangled!~/$Replace/) {
4729 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4730 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4731 #}
4732 }
4733 }
4734 return $Mangled;
4735}
4736
4737sub write_substitution($$)
4738{
4739 my ($Mangled, $Repl) = @_;
4740 if(defined $Repl->{$Mangled}
4741 and my $MnglNum = $Repl->{$Mangled}) {
4742 $Mangled = macro_mangle($MnglNum);
4743 }
4744 else
4745 {
4746 my @Repls = keys(%{$Repl});
4747 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4748 # FIXME: how to apply replacements? by num or by pos
4749 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4750 foreach my $MangledType (@Repls)
4751 {
4752 my $Replace = macro_mangle($Repl->{$MangledType});
4753 if($Mangled!~/$Replace/) {
4754 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4755 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4756 }
4757 }
4758 }
4759 return $Mangled;
4760}
4761
4762sub delete_keywords($)
4763{
4764 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004765 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004766 return $TypeName;
4767}
4768
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004769sub uncover_typedefs($$)
4770{
4771 my ($TypeName, $LibVersion) = @_;
4772 return "" if(not $TypeName);
4773 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4774 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4775 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004776 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004777 while($TypeName_New ne $TypeName_Pre)
4778 {
4779 $TypeName_Pre = $TypeName_New;
4780 my $TypeName_Copy = $TypeName_New;
4781 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004782 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004783 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004784 if(not $Intrinsic_Keywords{$1}) {
4785 $Words{$1} = 1;
4786 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004787 }
4788 foreach my $Word (keys(%Words))
4789 {
4790 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4791 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004792 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004793 if($BaseType_Name=~/\([\*]+\)/)
4794 { # FuncPtr
4795 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4796 {
4797 my $Type_Suffix = $1;
4798 $TypeName_New = $BaseType_Name;
4799 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004800 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004801 }
4802 }
4803 }
4804 else
4805 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004806 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004807 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004808 }
4809 }
4810 }
4811 }
4812 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4813}
4814
4815sub isInternal($)
4816{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004817 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4818 {
4819 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4820 {
4821 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4822 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4823 return 1;
4824 }
4825 }
4826 }
4827 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004828}
4829
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004830sub getDataVal($$)
4831{
4832 my ($InfoId, $TypeId) = @_;
4833 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4834 {
4835 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4836 {
4837 if(defined $LibInfo{$Version}{"info_type"}{$1}
4838 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004839 {
4840 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004841 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004842 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4843 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004844 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004845 if(my $Addr = getTreeAttr_Op($1)) {
4846 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004847 }
4848 }
4849 }
4850 }
4851 else {
4852 return getInitVal($1, $TypeId);
4853 }
4854 }
4855 }
4856 return undef;
4857}
4858
4859sub getInitVal($$)
4860{
4861 my ($InfoId, $TypeId) = @_;
4862 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4863 {
4864 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4865 {
4866 if($InfoType eq "integer_cst")
4867 {
4868 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004869 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004870 { # characters
4871 $Val = chr($Val);
4872 }
4873 return $Val;
4874 }
4875 elsif($InfoType eq "string_cst") {
4876 return getNodeStrCst($InfoId);
4877 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004878 elsif($InfoType eq "var_decl")
4879 {
4880 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4881 return $Name;
4882 }
4883 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004884 }
4885 }
4886 return undef;
4887}
4888
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004889sub set_Class_And_Namespace($)
4890{
4891 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004892 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004893 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004894 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004895 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004896 my $NSInfoId = $1;
4897 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4898 {
4899 if($InfoType eq "namespace_decl") {
4900 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4901 }
4902 elsif($InfoType eq "record_type") {
4903 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4904 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004906 }
4907 }
4908 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4909 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004910 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004911 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004912 { # skip
4913 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004914 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004915 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004916
4917 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004918}
4919
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004920sub debugMangling($)
4921{
4922 my $LibVersion = $_[0];
4923 my %Mangled = ();
4924 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4925 {
4926 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4927 {
4928 if($Mngl=~/\A(_Z|\?)/) {
4929 $Mangled{$Mngl}=$InfoId;
4930 }
4931 }
4932 }
4933 translateSymbols(keys(%Mangled), $LibVersion);
4934 foreach my $Mngl (keys(%Mangled))
4935 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004936 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4937 my $U2 = $tr_name{$Mngl};
4938 if($U1 ne $U2) {
4939 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004940 }
4941 }
4942}
4943
4944sub linkSymbol($)
4945{ # link symbols from shared libraries
4946 # with the symbols from header files
4947 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004948 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004949 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004950 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4951 or $EMERGENCY_MODE_48)
4952 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4953 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
4954 # GCC 4.8 doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004955 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004956 {
4957 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4958 return correct_incharge($InfoId, $Version, $Mangled);
4959 }
4960 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004961 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004962 or not $BinaryOnly
4963 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004964 { # 1. --headers-only mode
4965 # 2. not mangled src-only symbols
4966 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4967 return $Mangled;
4968 }
4969 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004970 }
4971 return "";
4972}
4973
4974sub setLanguage($$)
4975{
4976 my ($LibVersion, $Lang) = @_;
4977 if(not $UserLang) {
4978 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4979 }
4980}
4981
4982sub getSymbolInfo($)
4983{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004984 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004985 if(isInternal($InfoId)) {
4986 return;
4987 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004988 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4989 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004990 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4991 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004992 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004993 return;
4994 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004995 setFuncAccess($InfoId);
4996 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004997 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4998 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004999 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005000 return;
5001 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005002
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005003 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005004 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005005 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005006 if(not defined $TypeInfo{$Version}{$Return}
5007 or not $TypeInfo{$Version}{$Return}{"Name"})
5008 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005009 delete($SymbolInfo{$Version}{$InfoId});
5010 return;
5011 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005012 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005013 }
5014 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5015 {
5016 if(defined $MissedTypedef{$Version}{$Rid})
5017 {
5018 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5019 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5020 }
5021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005022 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005023 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5024 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005025 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005026 my $Orig = getFuncOrig($InfoId);
5027 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005028 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5029 {
5030 delete($SymbolInfo{$Version}{$InfoId});
5031 return;
5032 }
5033
5034 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005035 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005036 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005037 return;
5038 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005039
5040 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005041 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005042 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5043
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005044 my @TParams = getTParams($Orig, "Func");
5045 if(not @TParams)
5046 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005047 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005048 return;
5049 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005050 foreach my $Pos (0 .. $#TParams)
5051 {
5052 my $Val = $TParams[$Pos];
5053 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5054
5055 if($Tmpl)
5056 {
5057 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5058 {
5059 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5060 }
5061 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005062 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005063
5064 if($Tmpl)
5065 {
5066 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5067 {
5068 if($Pos>$#TParams)
5069 {
5070 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5071 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5072 }
5073 }
5074 }
5075
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005076 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5077 { # operator<< <T>, operator>> <T>
5078 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5079 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005080 if(@TParams) {
5081 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5082 }
5083 else {
5084 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5085 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005086 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005087 }
5088 else
5089 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005090 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005091 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005092 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5093 {
5094 if($OSgroup eq "windows")
5095 { # cut the offset
5096 $MnglName=~s/\@\d+\Z//g;
5097 }
5098 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5099
5100 # NOTE: mangling of some symbols may change depending on GCC version
5101 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5102 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5103 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005104
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005105 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005106 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005107 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005108 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005109 return;
5110 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005111 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005112 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005113 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005114 if($Skip)
5115 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005116 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005117 return;
5118 }
5119 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005120 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5121 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5122 }
5123
5124 if(set_Class_And_Namespace($InfoId))
5125 {
5126 delete($SymbolInfo{$Version}{$InfoId});
5127 return;
5128 }
5129
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005130 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5131 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005132 if(not defined $TypeInfo{$Version}{$ClassId}
5133 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5134 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005135 delete($SymbolInfo{$Version}{$InfoId});
5136 return;
5137 }
5138 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005139 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5140 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005141 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005142 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005143 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005144 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005145 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005146 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005147 }
5148 if($COMMON_LANGUAGE{$Version} eq "C++")
5149 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005150 # C++ or --headers-only mode
5151 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005152 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005153 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5154 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005155 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005156 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005157 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005158 if(my $Mangled = linkSymbol($InfoId)) {
5159 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005160 }
5161 }
5162 if($OStarget eq "windows")
5163 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005164 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005165 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005166 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005167 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005168 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005169 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005170 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005171 }
5172 }
5173 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005174 else
5175 { # not mangled in C
5176 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5177 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005178 if(not $CheckHeadersOnly
5179 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5180 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5181 {
5182 my $Incorrect = 0;
5183
5184 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5185 {
5186 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5187 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5188 { # mangled in the TU dump, but not mangled in the library
5189 $Incorrect = 1;
5190 }
5191 }
5192 else
5193 {
5194 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5195 { # all C++ functions are not mangled in the TU dump
5196 $Incorrect = 1;
5197 }
5198 }
5199 if($Incorrect)
5200 {
5201 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5202 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5203 }
5204 }
5205 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005206 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005207 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005208 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005209 return;
5210 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005211 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005212 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005213 { # identify virtual and pure virtual functions
5214 # NOTE: constructors cannot be virtual
5215 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5216 # in the TU dump, so taking it from the original symbol
5217 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5218 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5219 { # NOTE: D2 destructors are not present in a v-table
5220 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005222 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005223 if(isInline($InfoId)) {
5224 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005225 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005226 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005227 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5228 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005229 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5230 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005231 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005232 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005233 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005234 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005235 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005236 }
5237 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005238 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5239 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005240 if(not $ExtraDump)
5241 {
5242 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5243 { # non-target symbols
5244 delete($SymbolInfo{$Version}{$InfoId});
5245 return;
5246 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005248 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005249 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5250 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5251 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5252 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005253 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005254 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5255 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005256 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005257 return;
5258 }
5259 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005260 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005261 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005262 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005263 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005264 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005265 return;
5266 }
5267 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005268 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005269 }
5270 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005271 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5272 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5273 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005274 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005275 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5276 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005277 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005278 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005279 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005280 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005281 }
5282 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005283 if(getFuncLink($InfoId) eq "Static") {
5284 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005285 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005286 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5287 {
5288 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5289 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005290 if($Unmangled=~/\.\_\d/)
5291 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005292 delete($SymbolInfo{$Version}{$InfoId});
5293 return;
5294 }
5295 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005296 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005297
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005298 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5299 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005300 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005301 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5302 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005303 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005304
5305 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5306 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5307 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005308
5309 if($ExtraDump) {
5310 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5311 }
5312}
5313
5314sub guessHeader($)
5315{
5316 my $InfoId = $_[0];
5317 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5318 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5319 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5320 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5321 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5322 {
5323 if(get_filename($HPath) eq $Header)
5324 {
5325 my $HDir = get_filename(get_dirname($HPath));
5326 if($HDir ne "include"
5327 and $HDir=~/\A[a-z]+\Z/i) {
5328 return join_P($HDir, $Header);
5329 }
5330 }
5331 }
5332 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005333}
5334
5335sub isInline($)
5336{ # "body: undefined" in the tree
5337 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005338 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5339 {
5340 if($Info=~/ undefined /i) {
5341 return 0;
5342 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005343 }
5344 return 1;
5345}
5346
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005347sub hasThrow($)
5348{
5349 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5350 {
5351 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5352 return getTreeAttr_Unql($1, "unql");
5353 }
5354 }
5355 return 1;
5356}
5357
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005358sub getTypeId($)
5359{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005360 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5361 {
5362 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5363 return $1;
5364 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005365 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005366 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005367}
5368
5369sub setTypeMemb($$)
5370{
5371 my ($TypeId, $TypeAttr) = @_;
5372 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005373 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005374 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005375 if($TypeType eq "Enum")
5376 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005377 my $MInfoId = getTreeAttr_Csts($TypeId);
5378 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005379 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005380 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5381 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005382 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005383 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5384 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005385 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005386 }
5387 }
5388 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5389 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005390 my $MInfoId = getTreeAttr_Flds($TypeId);
5391 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005392 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005393 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5394 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005395 if(not $IType or $IType ne "field_decl")
5396 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005397
5398 if($IType eq "var_decl")
5399 { # static field
5400 $StaticFields = 1;
5401 }
5402
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005403 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005404 next;
5405 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005406 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005407 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005408 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005409 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005410 }
5411 if(not $StructMembName)
5412 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005413 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005414 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005415 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005416 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5417 if(isAnon($UnnamedTName))
5418 { # rename unnamed fields to unnamed0, unnamed1, ...
5419 $StructMembName = "unnamed".($UnnamedPos++);
5420 }
5421 }
5422 }
5423 if(not $StructMembName)
5424 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005425 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005426 next;
5427 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005428 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005429 if(defined $MissedTypedef{$Version}{$MembTypeId})
5430 {
5431 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5432 $MembTypeId = $AddedTid;
5433 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005434 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005435
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005436 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5437 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005438 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005439 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005440 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5441 }
5442 if($MInfo=~/spec:\s*mutable /)
5443 { # mutable fields
5444 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005445 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005446 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005447 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5448 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005449 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005450 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005451 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005452 }
5453 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005454 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005455 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5456 { # template
5457 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5458 }
5459 else {
5460 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5461 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005462 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005463
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005464 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005465 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005466 }
5467 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005468
5469 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005470}
5471
5472sub setFuncParams($)
5473{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005474 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005475 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005476
5477 my $FType = getFuncType($InfoId);
5478
5479 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005480 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005481 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5482 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005483 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005484 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005485 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5486 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005487 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005488 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5489 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005490 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005491 else
5492 { # skip
5493 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005494 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005495 # skip "this"-parameter
5496 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005497 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005498 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005499 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005500 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005501 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5502 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5503 if(not $ParamName)
5504 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005505 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005506 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005507 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5508 {
5509 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5510 $ParamTypeId = $AddedTid;
5511 }
5512 }
5513 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005514 if(not $PType or $PType eq "Unknown") {
5515 return 1;
5516 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005517 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005518 if(not $PTName) {
5519 return 1;
5520 }
5521 if($PTName eq "void") {
5522 last;
5523 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005524 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005525 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005526 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005527 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005528 $ParamInfoId = getNextElem($ParamInfoId);
5529 next;
5530 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005531 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005532
5533 if(my %Base = get_BaseType($ParamTypeId, $Version))
5534 {
5535 if(defined $Base{"Template"}) {
5536 return 1;
5537 }
5538 }
5539
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005540 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005541 if(my $Algn = getAlgn($ParamInfoId)) {
5542 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5543 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005544 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5545 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005546 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005547 }
5548 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005549 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005550 if($ParamName ne "this" or $FType ne "Method") {
5551 $PPos += 1;
5552 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005553 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005554 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005555 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005556 }
5557 return 0;
5558}
5559
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005560sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005561{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005562 my ($InfoId, $Vtt_Pos) = @_;
5563 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005564 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005565 my $FType = getFuncType($InfoId);
5566
5567 if($FType eq "Method")
5568 {
5569 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005570 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005571 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005572 if(not $ParamListElemId)
5573 { # foo(...)
5574 return 1;
5575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005576 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005577 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005578 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005579 { # actual params: may differ from formal args
5580 # formal int*const
5581 # actual: int*
5582 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005583 {
5584 $Vtt_Pos=-1;
5585 $ParamListElemId = getNextElem($ParamListElemId);
5586 next;
5587 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005588 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5589 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005590 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005591 $HaveVoid = 1;
5592 last;
5593 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005594 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005595 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005596 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5597 {
5598 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5599 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5600 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005601 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005602 }
5603 }
5604 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5605 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005606 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005607 { # params
5608 if($OldId ne $ParamTypeId)
5609 {
5610 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5611 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5612
5613 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5614 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5615 }
5616 }
5617 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005618 }
5619 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005620 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005621 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005622 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5623 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005624 if($PurpType eq "nop_expr")
5625 { # func ( const char* arg = (const char*)(void*)0 )
5626 $PurpId = getTreeAttr_Op($PurpId);
5627 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005628 my $Val = getInitVal($PurpId, $ParamTypeId);
5629 if(defined $Val) {
5630 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5631 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005632 }
5633 }
5634 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005635 if($Pos!=0 or $FType ne "Method") {
5636 $PPos += 1;
5637 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005638 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005639 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005640 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005641}
5642
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005643sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005644{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005645 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5646 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005647 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5648 return $1;
5649 }
5650 }
5651 return "";
5652}
5653
5654sub getTreeAttr_Chain($)
5655{
5656 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5657 {
5658 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5659 return $1;
5660 }
5661 }
5662 return "";
5663}
5664
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005665sub getTreeAttr_Unql($)
5666{
5667 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5668 {
5669 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5670 return $1;
5671 }
5672 }
5673 return "";
5674}
5675
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005676sub getTreeAttr_Scpe($)
5677{
5678 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5679 {
5680 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5681 return $1;
5682 }
5683 }
5684 return "";
5685}
5686
5687sub getTreeAttr_Type($)
5688{
5689 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5690 {
5691 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5692 return $1;
5693 }
5694 }
5695 return "";
5696}
5697
5698sub getTreeAttr_Name($)
5699{
5700 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5701 {
5702 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5703 return $1;
5704 }
5705 }
5706 return "";
5707}
5708
5709sub getTreeAttr_Mngl($)
5710{
5711 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5712 {
5713 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5714 return $1;
5715 }
5716 }
5717 return "";
5718}
5719
5720sub getTreeAttr_Prms($)
5721{
5722 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5723 {
5724 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5725 return $1;
5726 }
5727 }
5728 return "";
5729}
5730
5731sub getTreeAttr_Fncs($)
5732{
5733 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5734 {
5735 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5736 return $1;
5737 }
5738 }
5739 return "";
5740}
5741
5742sub getTreeAttr_Csts($)
5743{
5744 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5745 {
5746 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5747 return $1;
5748 }
5749 }
5750 return "";
5751}
5752
5753sub getTreeAttr_Purp($)
5754{
5755 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5756 {
5757 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5758 return $1;
5759 }
5760 }
5761 return "";
5762}
5763
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005764sub getTreeAttr_Op($)
5765{
5766 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5767 {
5768 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5769 return $1;
5770 }
5771 }
5772 return "";
5773}
5774
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005775sub getTreeAttr_Valu($)
5776{
5777 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5778 {
5779 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5780 return $1;
5781 }
5782 }
5783 return "";
5784}
5785
5786sub getTreeAttr_Flds($)
5787{
5788 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5789 {
5790 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5791 return $1;
5792 }
5793 }
5794 return "";
5795}
5796
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005797sub getTreeAttr_Binf($)
5798{
5799 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5800 {
5801 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5802 return $1;
5803 }
5804 }
5805 return "";
5806}
5807
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005808sub getTreeAttr_Args($)
5809{
5810 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5811 {
5812 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005813 return $1;
5814 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005815 }
5816 return "";
5817}
5818
5819sub getTreeValue($)
5820{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005821 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5822 {
5823 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5824 return $1;
5825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005826 }
5827 return "";
5828}
5829
5830sub getTreeAccess($)
5831{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005832 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005833 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005834 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5835 {
5836 my $Access = $1;
5837 if($Access eq "prot") {
5838 return "protected";
5839 }
5840 elsif($Access eq "priv") {
5841 return "private";
5842 }
5843 }
5844 elsif($Info=~/ protected /)
5845 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005846 return "protected";
5847 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005848 elsif($Info=~/ private /)
5849 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005850 return "private";
5851 }
5852 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005853 return "public";
5854}
5855
5856sub setFuncAccess($)
5857{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005858 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005859 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005860 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005861 }
5862 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005863 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005864 }
5865}
5866
5867sub setTypeAccess($$)
5868{
5869 my ($TypeId, $TypeAttr) = @_;
5870 my $Access = getTreeAccess($TypeId);
5871 if($Access eq "protected") {
5872 $TypeAttr->{"Protected"} = 1;
5873 }
5874 elsif($Access eq "private") {
5875 $TypeAttr->{"Private"} = 1;
5876 }
5877}
5878
5879sub setFuncKind($)
5880{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005881 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5882 {
5883 if($Info=~/pseudo tmpl/) {
5884 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5885 }
5886 elsif($Info=~/ constructor /) {
5887 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5888 }
5889 elsif($Info=~/ destructor /) {
5890 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005892 }
5893}
5894
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005895sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005896{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005897 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5898 {
5899 if($Info=~/spec[ ]*:[ ]*pure /) {
5900 return "PureVirt";
5901 }
5902 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5903 return "Virt";
5904 }
5905 elsif($Info=~/ pure\s+virtual /)
5906 { # support for old GCC versions
5907 return "PureVirt";
5908 }
5909 elsif($Info=~/ virtual /)
5910 { # support for old GCC versions
5911 return "Virt";
5912 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005913 }
5914 return "";
5915}
5916
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005917sub getFuncLink($)
5918{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005919 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5920 {
5921 if($Info=~/link[ ]*:[ ]*static /) {
5922 return "Static";
5923 }
5924 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005925 return $1;
5926 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005927 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005928 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005929}
5930
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005931sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005932{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005933 my ($Symbol, $LibVersion) = @_;
5934 return "" if(not $Symbol or not $LibVersion);
5935 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5936 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005937 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005938 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5939 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5940 }
5941 }
5942 if($NS)
5943 {
5944 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5945 return $NS;
5946 }
5947 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005948 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005949 while($NS=~s/::[^:]+\Z//)
5950 {
5951 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5952 return $NS;
5953 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005954 }
5955 }
5956 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005957
5958 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005959}
5960
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005961sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005962{
5963 my ($TypeName, $LibVersion) = @_;
5964 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005965 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005966 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005967 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5968 return $NS;
5969 }
5970 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005971 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005972 while($NS=~s/::[^:]+\Z//)
5973 {
5974 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5975 return $NS;
5976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005977 }
5978 }
5979 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005980 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005981}
5982
5983sub getNameSpace($)
5984{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005985 my $InfoId = $_[0];
5986 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005987 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005988 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005989 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005990 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005991 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005992 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5993 {
5994 my $NameSpace = getTreeStr($1);
5995 if($NameSpace eq "::")
5996 { # global namespace
5997 return "";
5998 }
5999 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6000 $NameSpace = $BaseNameSpace."::".$NameSpace;
6001 }
6002 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6003 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006004 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006005 else {
6006 return "";
6007 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006008 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006009 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006010 { # inside data type
6011 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6012 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006014 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006015 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006016 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006017}
6018
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006019sub getEnumMembVal($)
6020{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006021 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006022 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006023 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6024 {
6025 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6026 {
6027 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6028 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6029 return getTreeValue($1);
6030 }
6031 else
6032 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6033 return getTreeValue($1);
6034 }
6035 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006036 }
6037 }
6038 return "";
6039}
6040
6041sub getSize($)
6042{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006043 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6044 {
6045 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6046 return getTreeValue($1);
6047 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006048 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006049 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006050}
6051
6052sub getAlgn($)
6053{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006054 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6055 {
6056 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6057 return $1;
6058 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006059 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006060 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006061}
6062
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006063sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006064{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006065 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6066 {
6067 if($Info=~/ bitfield /) {
6068 return getSize($_[0]);
6069 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006070 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006071 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006072}
6073
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006074sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006075{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006076 if(my $Chan = getTreeAttr_Chan($_[0])) {
6077 return $Chan;
6078 }
6079 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6080 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006081 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006082 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006083}
6084
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006085sub registerHeader($$)
6086{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006087 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006088 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006089 return "";
6090 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006091 if(is_abs($Header) and not -f $Header)
6092 { # incorrect absolute path
6093 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006094 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006095 if(skipHeader($Header, $LibVersion))
6096 { # skip
6097 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006098 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006099 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6100 {
6101 detect_header_includes($Header_Path, $LibVersion);
6102
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006103 if(defined $Tolerance and $Tolerance=~/3/)
6104 { # 3 - skip headers that include non-Linux headers
6105 if($OSgroup ne "windows")
6106 {
6107 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6108 {
6109 if(specificHeader($Inc, "windows")) {
6110 return "";
6111 }
6112 }
6113 }
6114 }
6115
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006116 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6117 { # redirect
6118 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6119 or skipHeader($RHeader_Path, $LibVersion))
6120 { # skip
6121 return "";
6122 }
6123 $Header_Path = $RHeader_Path;
6124 }
6125 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6126 { # skip
6127 return "";
6128 }
6129
6130 if(my $HName = get_filename($Header_Path))
6131 { # register
6132 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6133 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6134 }
6135
6136 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6137 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006138 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006139 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006140 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006141 }
6142
6143 if($CheckHeadersOnly
6144 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6145 { # /usr/include/c++/4.6.1/...
6146 $STDCXX_TESTING = 1;
6147 }
6148
6149 return $Header_Path;
6150 }
6151 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006152}
6153
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006154sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006155{
6156 my ($Dir, $WithDeps, $LibVersion) = @_;
6157 $Dir=~s/[\/\\]+\Z//g;
6158 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006159 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006160
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006161 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006162 if($WithDeps)
6163 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006164 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6165 return;
6166 }
6167 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6168 $Mode = "DepsOnly";
6169 }
6170 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006171 else
6172 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006173 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6174 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6175 return;
6176 }
6177 }
6178 $Header_Dependency{$LibVersion}{$Dir} = 1;
6179 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6180 if($Mode eq "DepsOnly")
6181 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006182 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006183 $Header_Dependency{$LibVersion}{$Path} = 1;
6184 }
6185 return;
6186 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006187 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006188 {
6189 if($WithDeps)
6190 {
6191 my $SubDir = $Path;
6192 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6193 { # register all sub directories
6194 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6195 }
6196 }
6197 next if(is_not_header($Path));
6198 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006199 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006200 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006201 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6202 }
6203 }
6204 if(get_filename($Dir) eq "include")
6205 { # search for "lib/include/" directory
6206 my $LibDir = $Dir;
6207 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006208 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006209 }
6210 }
6211}
6212
6213sub parse_redirect($$$)
6214{
6215 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006216 my @Errors = ();
6217 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6218 push(@Errors, $1);
6219 }
6220 my $Redirect = "";
6221 foreach (@Errors)
6222 {
6223 s/\s{2,}/ /g;
6224 if(/(only|must\ include
6225 |update\ to\ include
6226 |replaced\ with
6227 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006228 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006229 {
6230 $Redirect = $2;
6231 last;
6232 }
6233 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6234 {
6235 $Redirect = $2;
6236 last;
6237 }
6238 elsif(/this\ header\ should\ not\ be\ used
6239 |programs\ should\ not\ directly\ include
6240 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6241 |is\ not\ supported\ API\ for\ general\ use
6242 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006243 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006244 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6245 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6246 }
6247 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006248 if($Redirect)
6249 {
6250 $Redirect=~s/\A<//g;
6251 $Redirect=~s/>\Z//g;
6252 }
6253 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006254}
6255
6256sub parse_includes($$)
6257{
6258 my ($Content, $Path) = @_;
6259 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006260 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006261 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006262 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006263 my $Method = substr($Header, 0, 1, "");
6264 substr($Header, length($Header)-1, 1, "");
6265 $Header = path_format($Header, $OSgroup);
6266 if($Method eq "\"" or is_abs($Header))
6267 {
6268 if(-e join_P(get_dirname($Path), $Header))
6269 { # relative path exists
6270 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006271 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006272 else
6273 { # include "..." that doesn't exist is equal to include <...>
6274 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006276 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006277 else {
6278 $Includes{$Header} = 1;
6279 }
6280 }
6281 if($ExtraInfo)
6282 {
6283 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6284 { # FT_FREETYPE_H
6285 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006286 }
6287 }
6288 return \%Includes;
6289}
6290
6291sub ignore_path($)
6292{
6293 my $Path = $_[0];
6294 if($Path=~/\~\Z/)
6295 {# skipping system backup files
6296 return 1;
6297 }
6298 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6299 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6300 return 1;
6301 }
6302 return 0;
6303}
6304
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006305sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006306{
6307 my ($ArrRef, $W) = @_;
6308 return if(length($W)<2);
6309 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6310}
6311
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006312sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006313{
6314 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006315
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006316 $H1=~s/\.[a-z]+\Z//ig;
6317 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006318
6319 my $Hname1 = get_filename($H1);
6320 my $Hname2 = get_filename($H2);
6321 my $HDir1 = get_dirname($H1);
6322 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006323 my $Dirname1 = get_filename($HDir1);
6324 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006325
6326 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6327 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6328
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006329 if($_[0] eq $_[1]
6330 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006331 return 0;
6332 }
6333 elsif($H1=~/\A\Q$H2\E/) {
6334 return 1;
6335 }
6336 elsif($H2=~/\A\Q$H1\E/) {
6337 return -1;
6338 }
6339 elsif($HDir1=~/\Q$Hname1\E/i
6340 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006341 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006342 return -1;
6343 }
6344 elsif($HDir2=~/\Q$Hname2\E/i
6345 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006346 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006347 return 1;
6348 }
6349 elsif($Hname1=~/\Q$Dirname1\E/i
6350 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006351 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006352 return -1;
6353 }
6354 elsif($Hname2=~/\Q$Dirname2\E/i
6355 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006356 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006357 return 1;
6358 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006359 elsif($Hname1=~/(config|lib|util)/i
6360 and $Hname2!~/(config|lib|util)/i)
6361 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006362 return -1;
6363 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006364 elsif($Hname2=~/(config|lib|util)/i
6365 and $Hname1!~/(config|lib|util)/i)
6366 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006367 return 1;
6368 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006369 else
6370 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006371 my $R1 = checkRelevance($H1);
6372 my $R2 = checkRelevance($H2);
6373 if($R1 and not $R2)
6374 { # libebook/e-book.h
6375 return -1;
6376 }
6377 elsif($R2 and not $R1)
6378 { # libebook/e-book.h
6379 return 1;
6380 }
6381 else
6382 {
6383 return (lc($H1) cmp lc($H2));
6384 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006385 }
6386}
6387
6388sub searchForHeaders($)
6389{
6390 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006391
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006392 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006393 registerGccHeaders();
6394
6395 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6396 { # c++ standard include paths
6397 registerCppHeaders();
6398 }
6399
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006400 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006401 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6402 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006403 {
6404 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006405 if($SystemRoot)
6406 {
6407 if(is_abs($Path)) {
6408 $Path = $SystemRoot.$Path;
6409 }
6410 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006411 if(not -e $Path) {
6412 exitStatus("Access_Error", "can't access \'$Path\'");
6413 }
6414 elsif(-f $Path) {
6415 exitStatus("Access_Error", "\'$Path\' - not a directory");
6416 }
6417 elsif(-d $Path)
6418 {
6419 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006420 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006421 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6422 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006423 }
6424 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006425 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006426 }
6427 }
6428 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006429 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006430 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6431 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006432
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006433 # registering directories
6434 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6435 {
6436 next if(not -e $Path);
6437 $Path = get_abs_path($Path);
6438 $Path = path_format($Path, $OSgroup);
6439 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006440 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006441 }
6442 elsif(-f $Path)
6443 {
6444 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006445 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006446 and not $LocalIncludes{$Dir})
6447 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006448 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006449 # if(my $OutDir = get_dirname($Dir))
6450 # { # registering the outer directory
6451 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6452 # and not $LocalIncludes{$OutDir}) {
6453 # registerDir($OutDir, 0, $LibVersion);
6454 # }
6455 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006456 }
6457 }
6458 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006459
6460 # clean memory
6461 %RegisteredDirs = ();
6462
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006463 # registering headers
6464 my $Position = 0;
6465 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6466 {
6467 if(is_abs($Dest) and not -e $Dest) {
6468 exitStatus("Access_Error", "can't access \'$Dest\'");
6469 }
6470 $Dest = path_format($Dest, $OSgroup);
6471 if(is_header($Dest, 1, $LibVersion))
6472 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006473 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006474 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6475 }
6476 }
6477 elsif(-d $Dest)
6478 {
6479 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006480 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006481 {
6482 next if(ignore_path($Path));
6483 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006484 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006485 push(@Registered, $HPath);
6486 }
6487 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006488 @Registered = sort {sortHeaders($a, $b)} @Registered;
6489 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006490 foreach my $Path (@Registered) {
6491 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6492 }
6493 }
6494 else {
6495 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6496 }
6497 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006498
6499 if(defined $Tolerance and $Tolerance=~/4/)
6500 { # 4 - skip headers included by others
6501 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6502 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006503 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006504 delete($Registered_Headers{$LibVersion}{$Path});
6505 }
6506 }
6507 }
6508
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006509 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6510 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006511 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006512 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006513 if(is_abs($Header) and not -f $Header) {
6514 exitStatus("Access_Error", "can't access file \'$Header\'");
6515 }
6516 $Header = path_format($Header, $OSgroup);
6517 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6518 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006519 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006520 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006521 }
6522 else {
6523 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6524 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006525 }
6526 }
6527 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6528 { # set relative paths (for duplicates)
6529 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6530 { # search for duplicates
6531 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6532 my $Prefix = get_dirname($FirstPath);
6533 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6534 { # detect a shortest distinguishing prefix
6535 my $NewPrefix = $1;
6536 my %Identity = ();
6537 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6538 {
6539 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6540 $Identity{$Path} = $1;
6541 }
6542 }
6543 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006544 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006545 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6546 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6547 }
6548 last;
6549 }
6550 $Prefix = $NewPrefix; # increase prefix
6551 }
6552 }
6553 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006554
6555 # clean memory
6556 %HeaderName_Paths = ();
6557
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006558 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6559 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006560 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006561 my ($Pos, $PairPos) = (-1, -1);
6562 my ($Path, $PairPath) = ();
6563 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6564 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6565 foreach my $Header_Path (@Paths)
6566 {
6567 if(get_filename($Header_Path) eq $PairName)
6568 {
6569 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6570 $PairPath = $Header_Path;
6571 }
6572 if(get_filename($Header_Path) eq $HeaderName)
6573 {
6574 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6575 $Path = $Header_Path;
6576 }
6577 }
6578 if($PairPos!=-1 and $Pos!=-1
6579 and int($PairPos)<int($Pos))
6580 {
6581 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6582 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6583 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6584 }
6585 }
6586 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6587 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6588 }
6589}
6590
6591sub detect_real_includes($$)
6592{
6593 my ($AbsPath, $LibVersion) = @_;
6594 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6595 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6596 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6597 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6598 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006599 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6600
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006601 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6602 return () if(not $Path);
6603 open(PREPROC, $Path);
6604 while(<PREPROC>)
6605 {
6606 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6607 {
6608 my $Include = path_format($1, $OSgroup);
6609 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6610 next;
6611 }
6612 if($Include eq $AbsPath) {
6613 next;
6614 }
6615 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6616 }
6617 }
6618 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006619 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6620}
6621
6622sub detect_header_includes($$)
6623{
6624 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006625 return if(not $LibVersion or not $Path);
6626 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6627 return;
6628 }
6629 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6630
6631 if(not -e $Path) {
6632 return;
6633 }
6634
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006635 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006636 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6637 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006638 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006639 {
6640 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006641 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006642 }
6643 if($RedirectPath ne $Path) {
6644 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6645 }
6646 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006647 else
6648 { # can't find
6649 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6650 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006651 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006652 if(my $Inc = parse_includes($Content, $Path))
6653 {
6654 foreach my $Include (keys(%{$Inc}))
6655 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006656 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006657
6658 if(defined $Tolerance and $Tolerance=~/4/)
6659 {
6660 if(my $HPath = identifyHeader($Include, $LibVersion))
6661 {
6662 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6663 }
6664 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006666 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006667}
6668
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006669sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006670{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006671 my $Path = $_[0];
6672 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006673 if($OStarget eq "symbian")
6674 {
6675 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6676 { # epoc32/include/libc/{stdio, ...}.h
6677 return 1;
6678 }
6679 }
6680 else
6681 {
6682 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6683 { # /usr/include/{stdio, ...}.h
6684 return 1;
6685 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006687 return 0;
6688}
6689
6690sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006691{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006692 my $Dir = $_[0];
6693 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006694 if($OStarget eq "symbian")
6695 {
6696 if(get_filename($OutDir) eq "libc"
6697 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6698 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6699 return 1;
6700 }
6701 }
6702 else
6703 { # linux
6704 if($OutDir eq "/usr/include"
6705 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6706 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6707 return 1;
6708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006709 }
6710 return 0;
6711}
6712
6713sub detect_recursive_includes($$)
6714{
6715 my ($AbsPath, $LibVersion) = @_;
6716 return () if(not $AbsPath);
6717 if(isCyclical(\@RecurInclude, $AbsPath)) {
6718 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6719 }
6720 my ($AbsDir, $Name) = separate_path($AbsPath);
6721 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006722 { # system GLIBC internals
6723 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006724 }
6725 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6726 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6727 }
6728 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006729
6730 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6731 { # skip /usr/include/c++/*/ headers
6732 return () if(not $ExtraInfo);
6733 }
6734
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006735 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006736 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006737 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006738 { # check "real" (non-"model") include paths
6739 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6740 pop(@RecurInclude);
6741 return @Paths;
6742 }
6743 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6744 detect_header_includes($AbsPath, $LibVersion);
6745 }
6746 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6747 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006748 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006749 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006750 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006751 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006752 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006753 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006754 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006755 }
6756 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006757 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006758 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006759 { # search for the nearest header
6760 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006761 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006762 if(-f $Candidate) {
6763 $HPath = $Candidate;
6764 }
6765 }
6766 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006767 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006768 }
6769 next if(not $HPath);
6770 if($HPath eq $AbsPath) {
6771 next;
6772 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006773
6774 if($Debug)
6775 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006776# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6777# {
6778# print STDERR "$AbsPath -> $HPath\n";
6779# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006780 }
6781
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006782 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6783 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006784 { # only include <...>, skip include "..." prefixes
6785 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6786 }
6787 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6788 {
6789 if($IncPath eq $AbsPath) {
6790 next;
6791 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006792 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6793 if($RIncType==-1)
6794 { # include "..."
6795 $RIncType = $IncType;
6796 }
6797 elsif($RIncType==2)
6798 {
6799 if($IncType!=-1) {
6800 $RIncType = $IncType;
6801 }
6802 }
6803 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006804 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6805 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6806 }
6807 }
6808 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6809 {
6810 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6811 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6812 { # distinguish math.h from glibc and math.h from the tested library
6813 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6814 last;
6815 }
6816 }
6817 }
6818 pop(@RecurInclude);
6819 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6820}
6821
6822sub find_in_framework($$$)
6823{
6824 my ($Header, $Framework, $LibVersion) = @_;
6825 return "" if(not $Header or not $Framework or not $LibVersion);
6826 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6827 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6828 }
6829 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6830 {
6831 if(get_filename($Dependency) eq $Framework
6832 and -f get_dirname($Dependency)."/".$Header) {
6833 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6834 }
6835 }
6836 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6837}
6838
6839sub find_in_defaults($)
6840{
6841 my $Header = $_[0];
6842 return "" if(not $Header);
6843 if(defined $Cache{"find_in_defaults"}{$Header}) {
6844 return $Cache{"find_in_defaults"}{$Header};
6845 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006846 foreach my $Dir (@DefaultIncPaths,
6847 @DefaultGccPaths,
6848 @DefaultCppPaths,
6849 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006850 {
6851 next if(not $Dir);
6852 if(-f $Dir."/".$Header) {
6853 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6854 }
6855 }
6856 return ($Cache{"find_in_defaults"}{$Header}="");
6857}
6858
6859sub cmp_paths($$)
6860{
6861 my ($Path1, $Path2) = @_;
6862 my @Parts1 = split(/[\/\\]/, $Path1);
6863 my @Parts2 = split(/[\/\\]/, $Path2);
6864 foreach my $Num (0 .. $#Parts1)
6865 {
6866 my $Part1 = $Parts1[$Num];
6867 my $Part2 = $Parts2[$Num];
6868 if($GlibcDir{$Part1}
6869 and not $GlibcDir{$Part2}) {
6870 return 1;
6871 }
6872 elsif($GlibcDir{$Part2}
6873 and not $GlibcDir{$Part1}) {
6874 return -1;
6875 }
6876 elsif($Part1=~/glib/
6877 and $Part2!~/glib/) {
6878 return 1;
6879 }
6880 elsif($Part1!~/glib/
6881 and $Part2=~/glib/) {
6882 return -1;
6883 }
6884 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6885 return $CmpRes;
6886 }
6887 }
6888 return 0;
6889}
6890
6891sub checkRelevance($)
6892{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006893 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006894 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006895
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006896 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006897 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006898 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006899
6900 my $Name = lc(get_filename($Path));
6901 my $Dir = lc(get_dirname($Path));
6902
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006903 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006904
6905 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006906 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006907 my $Len = length($Token);
6908 next if($Len<=1);
6909 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6910 { # include/evolution-data-server-1.4/libebook/e-book.h
6911 return 1;
6912 }
6913 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006914 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006915 return 1;
6916 }
6917 }
6918 return 0;
6919}
6920
6921sub checkFamily(@)
6922{
6923 my @Paths = @_;
6924 return 1 if($#Paths<=0);
6925 my %Prefix = ();
6926 foreach my $Path (@Paths)
6927 {
6928 if($SystemRoot) {
6929 $Path = cut_path_prefix($Path, $SystemRoot);
6930 }
6931 if(my $Dir = get_dirname($Path))
6932 {
6933 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6934 $Prefix{$Dir} += 1;
6935 $Prefix{get_dirname($Dir)} += 1;
6936 }
6937 }
6938 foreach (sort keys(%Prefix))
6939 {
6940 if(get_depth($_)>=3
6941 and $Prefix{$_}==$#Paths+1) {
6942 return 1;
6943 }
6944 }
6945 return 0;
6946}
6947
6948sub isAcceptable($$$)
6949{
6950 my ($Header, $Candidate, $LibVersion) = @_;
6951 my $HName = get_filename($Header);
6952 if(get_dirname($Header))
6953 { # with prefix
6954 return 1;
6955 }
6956 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6957 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6958 return 1;
6959 }
6960 if(checkRelevance($Candidate))
6961 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6962 return 1;
6963 }
6964 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6965 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6966 # /usr/include/qt4/Qt/qsslconfiguration.h
6967 return 1;
6968 }
6969 if($OStarget eq "symbian")
6970 {
6971 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6972 return 1;
6973 }
6974 }
6975 return 0;
6976}
6977
6978sub isRelevant($$$)
6979{ # disallow to search for "abstract" headers in too deep directories
6980 my ($Header, $Candidate, $LibVersion) = @_;
6981 my $HName = get_filename($Header);
6982 if($OStarget eq "symbian")
6983 {
6984 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6985 return 0;
6986 }
6987 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006988 if($OStarget ne "bsd")
6989 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006990 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6991 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6992 return 0;
6993 }
6994 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006995 if($OStarget ne "windows")
6996 {
6997 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6998 { # skip /usr/include/wine/msvcrt
6999 return 0;
7000 }
7001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007002 if(not get_dirname($Header)
7003 and $Candidate=~/[\/\\]wx[\/\\]/)
7004 { # do NOT search in system /wx/ directory
7005 # for headers without a prefix: sstream.h
7006 return 0;
7007 }
7008 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7009 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7010 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7011 return 0;
7012 }
7013 if($Candidate=~/[\/\\]asm-/
7014 and (my $Arch = getArch($LibVersion)) ne "unknown")
7015 { # arch-specific header files
7016 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7017 {# skip ../asm-arm/ if using x86 architecture
7018 return 0;
7019 }
7020 }
7021 my @Candidates = getSystemHeaders($HName, $LibVersion);
7022 if($#Candidates==1)
7023 { # unique header
7024 return 1;
7025 }
7026 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7027 if($#SCandidates==1)
7028 { # unique name
7029 return 1;
7030 }
7031 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7032 if(get_depth($Candidate)-$SystemDepth>=5)
7033 { # abstract headers in too deep directories
7034 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7035 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7036 return 0;
7037 }
7038 }
7039 if($Header eq "parser.h"
7040 and $Candidate!~/\/libxml2\//)
7041 { # select parser.h from xml2 library
7042 return 0;
7043 }
7044 if(not get_dirname($Header)
7045 and keys(%{$SystemHeaders{$HName}})>=3)
7046 { # many headers with the same name
7047 # like thread.h included without a prefix
7048 if(not checkFamily(@Candidates)) {
7049 return 0;
7050 }
7051 }
7052 return 1;
7053}
7054
7055sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007056{ # cache function
7057 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7058 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7059 }
7060 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7061}
7062
7063sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007064{
7065 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007066 if(-f $Header) {
7067 return $Header;
7068 }
7069 if(is_abs($Header) and not -f $Header)
7070 { # incorrect absolute path
7071 return "";
7072 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007073 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007074 { # too abstract configuration headers
7075 return "";
7076 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007077 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007078 if($OSgroup ne "windows")
7079 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007080 if(defined $WinHeaders{lc($HName)}
7081 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007082 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007083 return "";
7084 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007085 }
7086 if($OSgroup ne "macos")
7087 {
7088 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007089 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007090 return "";
7091 }
7092 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007093
7094 if(defined $ObsoleteHeaders{$HName})
7095 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007096 return "";
7097 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007098 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7099 {
7100 if(defined $AlienHeaders{$HName}
7101 or defined $AlienHeaders{$Header})
7102 { # alien headers from other systems
7103 return "";
7104 }
7105 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007106
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007107 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007108 { # search in default paths
7109 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007110 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007111 }
7112 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007113 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007114 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007115 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007116 }
7117 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7118 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7119 {
7120 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007121 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007122 }
7123 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007124 # error
7125 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007126}
7127
7128sub getSystemHeaders($$)
7129{
7130 my ($Header, $LibVersion) = @_;
7131 my @Candidates = ();
7132 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7133 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007134 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007135 next;
7136 }
7137 push(@Candidates, $Candidate);
7138 }
7139 return @Candidates;
7140}
7141
7142sub cut_path_prefix($$)
7143{
7144 my ($Path, $Prefix) = @_;
7145 return $Path if(not $Prefix);
7146 $Prefix=~s/[\/\\]+\Z//;
7147 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7148 return $Path;
7149}
7150
7151sub is_default_include_dir($)
7152{
7153 my $Dir = $_[0];
7154 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007155 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007156}
7157
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007158sub identifyHeader($$)
7159{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007160 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007161 if(not $Header) {
7162 return "";
7163 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007164 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007165 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7166 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007167 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007168 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007169}
7170
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007171sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007172{ # search for header by absolute path, relative path or name
7173 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007174 if(-f $Header)
7175 { # it's relative or absolute path
7176 return get_abs_path($Header);
7177 }
7178 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7179 and my $HeaderDir = find_in_defaults($Header))
7180 { # search for libc headers in the /usr/include
7181 # for non-libc target library before searching
7182 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007183 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007184 }
7185 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7186 { # search in the target library paths
7187 return $Path;
7188 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007189 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007190 { # search in the internal GCC include paths
7191 return $DefaultGccHeader{$Header};
7192 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007193 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007194 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007195 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007196 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007197 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007198 { # search in the default G++ include paths
7199 return $DefaultCppHeader{$Header};
7200 }
7201 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7202 { # search everywhere in the system
7203 return $AnyPath;
7204 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007205 elsif($OSgroup eq "macos")
7206 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7207 if(my $Dir = get_dirname($Header))
7208 {
7209 my $RelPath = "Headers\/".get_filename($Header);
7210 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007211 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007212 }
7213 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007214 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007215 # cannot find anything
7216 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007217}
7218
7219sub getLocation($)
7220{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007221 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7222 {
7223 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007224 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007225 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007226 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007227 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007228}
7229
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007230sub getNameByInfo($)
7231{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007232 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007233 {
7234 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7235 {
7236 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7237 {
7238 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7239 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007240 my $Str = $1;
7241 if($CppMode{$Version}
7242 and $Str=~/\Ac99_(.+)\Z/)
7243 {
7244 if($CppKeywords_A{$1}) {
7245 $Str=$1;
7246 }
7247 }
7248 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007249 }
7250 }
7251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007252 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007253 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007254}
7255
7256sub getTreeStr($)
7257{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007258 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007259 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007260 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7261 {
7262 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007263 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007264 and $Str=~/\Ac99_(.+)\Z/)
7265 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007266 if($CppKeywords_A{$1}) {
7267 $Str=$1;
7268 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007269 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007270 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007272 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007273 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007274}
7275
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007276sub getFuncShortName($)
7277{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007278 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007279 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007280 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007281 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007282 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007283 {
7284 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7285 {
7286 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7287 return "operator ".$RName;
7288 }
7289 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007290 }
7291 else
7292 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007293 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7294 {
7295 if(my $Ind = $Operator_Indication{$1}) {
7296 return "operator".$Ind;
7297 }
7298 elsif(not $UnknownOperator{$1})
7299 {
7300 printMsg("WARNING", "unknown operator $1");
7301 $UnknownOperator{$1} = 1;
7302 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007303 }
7304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007305 }
7306 else
7307 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007308 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7309 return getTreeStr($1);
7310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007311 }
7312 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007313 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007314}
7315
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007316sub getFuncReturn($)
7317{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007318 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7319 {
7320 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7321 {
7322 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7323 return $1;
7324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007325 }
7326 }
7327 return "";
7328}
7329
7330sub getFuncOrig($)
7331{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007332 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7333 {
7334 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7335 return $1;
7336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007337 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007338 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007339}
7340
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007341sub unmangleArray(@)
7342{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007343 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007344 { # MSVC mangling
7345 my $UndNameCmd = get_CmdPath("undname");
7346 if(not $UndNameCmd) {
7347 exitStatus("Not_Found", "can't find \"undname\"");
7348 }
7349 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007350 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007351 }
7352 else
7353 { # GCC mangling
7354 my $CppFiltCmd = get_CmdPath("c++filt");
7355 if(not $CppFiltCmd) {
7356 exitStatus("Not_Found", "can't find c++filt in PATH");
7357 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007358 if(not defined $CPPFILT_SUPPORT_FILE)
7359 {
7360 my $Info = `$CppFiltCmd -h 2>&1`;
7361 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7362 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007363 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007364 if($CPPFILT_SUPPORT_FILE)
7365 { # new versions of c++filt can take a file
7366 if($#_>$MAX_CPPFILT_FILE_SIZE)
7367 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7368 # this is fixed in the oncoming version of Binutils
7369 my @Half = splice(@_, 0, ($#_+1)/2);
7370 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007371 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007372 else
7373 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007374 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7375 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7376 if($?==139)
7377 { # segmentation fault
7378 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7379 }
7380 return split(/\n/, $Res);
7381 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007382 }
7383 else
7384 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007385 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7386 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007387 my @Half = splice(@_, 0, ($#_+1)/2);
7388 return (unmangleArray(@Half), unmangleArray(@_))
7389 }
7390 else
7391 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007392 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007393 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7394 if($?==139)
7395 { # segmentation fault
7396 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7397 }
7398 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007399 }
7400 }
7401 }
7402}
7403
7404sub get_SignatureNoInfo($$)
7405{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007406 my ($Symbol, $LibVersion) = @_;
7407 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
7408 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007409 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007410 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007411 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007412 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007413 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04007414 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007415 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
7416 $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;
7417 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007418 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007419 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007420 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007421 $Signature .= " [data]";
7422 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007423 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007424 $Signature .= " (...)";
7425 }
7426 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007427 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007428 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04007429 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007430 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
7431 }
7432 if($SymbolVersion) {
7433 $Signature .= $VersionSpec.$SymbolVersion;
7434 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007435 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007436}
7437
7438sub get_ChargeLevel($$)
7439{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007440 my ($Symbol, $LibVersion) = @_;
7441 return "" if($Symbol!~/\A(_Z|\?)/);
7442 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7443 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007444 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007445 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007446 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007447 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007448 return "[in-charge]";
7449 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007450 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007451 return "[not-in-charge]";
7452 }
7453 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007454 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007455 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007456 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007457 return "[in-charge]";
7458 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007459 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007460 return "[not-in-charge]";
7461 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007462 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007463 return "[in-charge-deleting]";
7464 }
7465 }
7466 }
7467 else
7468 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007469 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007470 return "[in-charge]";
7471 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007472 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007473 return "[not-in-charge]";
7474 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007475 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007476 return "[in-charge]";
7477 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007478 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007479 return "[not-in-charge]";
7480 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007481 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007482 return "[in-charge-deleting]";
7483 }
7484 }
7485 return "";
7486}
7487
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007488sub get_Signature_M($$)
7489{
7490 my ($Symbol, $LibVersion) = @_;
7491 my $Signature_M = $tr_name{$Symbol};
7492 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7493 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007494 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007495 }
7496 return $Signature_M;
7497}
7498
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007499sub get_Signature($$)
7500{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007501 my ($Symbol, $LibVersion) = @_;
7502 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7503 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007504 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007505 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
7506 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007507 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007508 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007509 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007510 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007511 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7512 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007513 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007514 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7515 {
7516 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7517 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7518 $Signature .= "~";
7519 }
7520 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007521 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007522 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007523 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007524 }
7525 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007526 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007527 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007528 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7529 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007530 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007531 else
7532 {
7533 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007534 }
7535 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007536 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007537 {
7538 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007539 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007540 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007541 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007542 if(not $ParamTypeName) {
7543 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7544 }
7545 foreach my $Typedef (keys(%ChangedTypedef))
7546 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007547 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7548 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7549 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007550 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007551 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7552 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007553 if($ParamName eq "this"
7554 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007555 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007556 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007557 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007558 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007559 }
7560 else {
7561 push(@ParamArray, $ParamTypeName);
7562 }
7563 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007564 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7565 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007566 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007567 }
7568 else
7569 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007570 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007571 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007572 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007573 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007574 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007575 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7576 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007577 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007578 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007579 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7580 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007581 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007582 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007583 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7584 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007585 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007586 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007587 }
7588 }
7589 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007590 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007591 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007592 }
7593 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007594 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007595 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007596 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007597}
7598
7599sub create_member_decl($$)
7600{
7601 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007602 if($TName=~/\([\*]+\)/)
7603 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007604 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7605 return $TName;
7606 }
7607 else
7608 {
7609 my @ArraySizes = ();
7610 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7611 push(@ArraySizes, $1);
7612 }
7613 return $TName." ".$Member.join("", @ArraySizes);
7614 }
7615}
7616
7617sub getFuncType($)
7618{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007619 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7620 {
7621 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7622 {
7623 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7624 {
7625 if($Type eq "method_type") {
7626 return "Method";
7627 }
7628 elsif($Type eq "function_type") {
7629 return "Function";
7630 }
7631 else {
7632 return "Other";
7633 }
7634 }
7635 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007636 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007637 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007638}
7639
7640sub getFuncTypeId($)
7641{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007642 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7643 {
7644 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7645 return $1;
7646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007647 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007648 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007649}
7650
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007651sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007652{ # "._N" or "$_N" in older GCC versions
7653 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007654}
7655
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007656sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007657{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007658 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7659 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007660 }
7661
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007662 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007663
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007664 if($_[1] ne "S")
7665 {
7666 $N=~s/\A[ ]+//g;
7667 $N=~s/[ ]+\Z//g;
7668 $N=~s/[ ]{2,}/ /g;
7669 }
7670
7671 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007672
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007673 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007674
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007675 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7676 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007677
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007678 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007679
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007680 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007681
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007682 if($_[1] eq "S")
7683 {
7684 if(index($N, "operator")!=-1) {
7685 $N=~s/\b(operator[ ]*)> >/$1>>/;
7686 }
7687 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007688
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007689 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007690}
7691
7692sub get_HeaderDeps($$)
7693{
7694 my ($AbsPath, $LibVersion) = @_;
7695 return () if(not $AbsPath or not $LibVersion);
7696 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7697 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7698 }
7699 my %IncDir = ();
7700 detect_recursive_includes($AbsPath, $LibVersion);
7701 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7702 {
7703 next if(not $HeaderPath);
7704 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7705 my $Dir = get_dirname($HeaderPath);
7706 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7707 {
7708 my $Dep = $Dir;
7709 if($Prefix)
7710 {
7711 if($OSgroup eq "windows")
7712 { # case insensitive seach on windows
7713 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7714 next;
7715 }
7716 }
7717 elsif($OSgroup eq "macos")
7718 { # seach in frameworks
7719 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7720 {
7721 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7722 {# frameworks
7723 my ($HFramework, $HName) = ($1, $2);
7724 $Dep = $HFramework;
7725 }
7726 else
7727 {# mismatch
7728 next;
7729 }
7730 }
7731 }
7732 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7733 { # Linux, FreeBSD
7734 next;
7735 }
7736 }
7737 if(not $Dep)
7738 { # nothing to include
7739 next;
7740 }
7741 if(is_default_include_dir($Dep))
7742 { # included by the compiler
7743 next;
7744 }
7745 if(get_depth($Dep)==1)
7746 { # too short
7747 next;
7748 }
7749 if(isLibcDir($Dep))
7750 { # do NOT include /usr/include/{sys,bits}
7751 next;
7752 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007753 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007754 }
7755 }
7756 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7757 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7758}
7759
7760sub sortIncPaths($$)
7761{
7762 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007763 if(not $ArrRef or $#{$ArrRef}<0) {
7764 return $ArrRef;
7765 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007766 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7767 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007768 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007769 return $ArrRef;
7770}
7771
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007772sub sortDeps($$$)
7773{
7774 if($Header_Dependency{$_[2]}{$_[0]}
7775 and not $Header_Dependency{$_[2]}{$_[1]}) {
7776 return 1;
7777 }
7778 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7779 and $Header_Dependency{$_[2]}{$_[1]}) {
7780 return -1;
7781 }
7782 return 0;
7783}
7784
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007785sub join_P($$)
7786{
7787 my $S = "/";
7788 if($OSgroup eq "windows") {
7789 $S = "\\";
7790 }
7791 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007792}
7793
7794sub get_namespace_additions($)
7795{
7796 my $NameSpaces = $_[0];
7797 my ($Additions, $AddNameSpaceId) = ("", 1);
7798 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7799 {
7800 next if($SkipNameSpaces{$Version}{$NS});
7801 next if(not $NS or $NameSpaces->{$NS}==-1);
7802 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7803 next if($NS=~/\A__/i);
7804 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007805 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007806 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7807 my @NS_Parts = split(/::/, $NS);
7808 next if($#NS_Parts==-1);
7809 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7810 foreach my $NS_Part (@NS_Parts)
7811 {
7812 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7813 $TypeDecl_Suffix .= "}";
7814 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007815 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007816 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7817 $Additions.=" $TypeDecl\n $FuncDecl\n";
7818 $AddNameSpaceId+=1;
7819 }
7820 return $Additions;
7821}
7822
7823sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007824{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007825 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007826 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007827 if($Fmt eq "windows")
7828 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007829 $Path=~s/\//\\/g;
7830 $Path=lc($Path);
7831 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007832 else
7833 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007834 $Path=~s/\\/\//g;
7835 }
7836 return $Path;
7837}
7838
7839sub inc_opt($$)
7840{
7841 my ($Path, $Style) = @_;
7842 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007843 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007844 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007845 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007846 return "-I\"".path_format($Path, "unix")."\"";
7847 }
7848 elsif($OSgroup eq "macos"
7849 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007850 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007851 return "-F".esc(get_dirname($Path));
7852 }
7853 else {
7854 return "-I".esc($Path);
7855 }
7856 }
7857 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007858 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007859 }
7860 return "";
7861}
7862
7863sub platformSpecs($)
7864{
7865 my $LibVersion = $_[0];
7866 my $Arch = getArch($LibVersion);
7867 if($OStarget eq "symbian")
7868 { # options for GCCE compiler
7869 my %Symbian_Opts = map {$_=>1} (
7870 "-D__GCCE__",
7871 "-DUNICODE",
7872 "-fexceptions",
7873 "-D__SYMBIAN32__",
7874 "-D__MARM_INTERWORK__",
7875 "-D_UNICODE",
7876 "-D__S60_50__",
7877 "-D__S60_3X__",
7878 "-D__SERIES60_3X__",
7879 "-D__EPOC32__",
7880 "-D__MARM__",
7881 "-D__EABI__",
7882 "-D__MARM_ARMV5__",
7883 "-D__SUPPORT_CPP_EXCEPTIONS__",
7884 "-march=armv5t",
7885 "-mapcs",
7886 "-mthumb-interwork",
7887 "-DEKA2",
7888 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7889 );
7890 return join(" ", keys(%Symbian_Opts));
7891 }
7892 elsif($OSgroup eq "windows"
7893 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7894 { # add options to MinGW compiler
7895 # to simulate the MSVC compiler
7896 my %MinGW_Opts = map {$_=>1} (
7897 "-D_WIN32",
7898 "-D_STDCALL_SUPPORTED",
7899 "-D__int64=\"long long\"",
7900 "-D__int32=int",
7901 "-D__int16=short",
7902 "-D__int8=char",
7903 "-D__possibly_notnullterminated=\" \"",
7904 "-D__nullterminated=\" \"",
7905 "-D__nullnullterminated=\" \"",
7906 "-D__w64=\" \"",
7907 "-D__ptr32=\" \"",
7908 "-D__ptr64=\" \"",
7909 "-D__forceinline=inline",
7910 "-D__inline=inline",
7911 "-D__uuidof(x)=IID()",
7912 "-D__try=",
7913 "-D__except(x)=",
7914 "-D__declspec(x)=__attribute__((x))",
7915 "-D__pragma(x)=",
7916 "-D_inline=inline",
7917 "-D__forceinline=__inline",
7918 "-D__stdcall=__attribute__((__stdcall__))",
7919 "-D__cdecl=__attribute__((__cdecl__))",
7920 "-D__fastcall=__attribute__((__fastcall__))",
7921 "-D__thiscall=__attribute__((__thiscall__))",
7922 "-D_stdcall=__attribute__((__stdcall__))",
7923 "-D_cdecl=__attribute__((__cdecl__))",
7924 "-D_fastcall=__attribute__((__fastcall__))",
7925 "-D_thiscall=__attribute__((__thiscall__))",
7926 "-DSHSTDAPI_(x)=x",
7927 "-D_MSC_EXTENSIONS",
7928 "-DSECURITY_WIN32",
7929 "-D_MSC_VER=1500",
7930 "-D_USE_DECLSPECS_FOR_SAL",
7931 "-D__noop=\" \"",
7932 "-DDECLSPEC_DEPRECATED=\" \"",
7933 "-D__builtin_alignof(x)=__alignof__(x)",
7934 "-DSORTPP_PASS");
7935 if($Arch eq "x86") {
7936 $MinGW_Opts{"-D_M_IX86=300"}=1;
7937 }
7938 elsif($Arch eq "x86_64") {
7939 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7940 }
7941 elsif($Arch eq "ia64") {
7942 $MinGW_Opts{"-D_M_IA64=300"}=1;
7943 }
7944 return join(" ", keys(%MinGW_Opts));
7945 }
7946 return "";
7947}
7948
7949my %C_Structure = map {$_=>1} (
7950# FIXME: Can't separate union and struct data types before dumping,
7951# so it sometimes cause compilation errors for unknown reason
7952# when trying to declare TYPE* tmp_add_class_N
7953# This is a list of such structures + list of other C structures
7954 "sigval",
7955 "sigevent",
7956 "sigaction",
7957 "sigvec",
7958 "sigstack",
7959 "timeval",
7960 "timezone",
7961 "rusage",
7962 "rlimit",
7963 "wait",
7964 "flock",
7965 "stat",
7966 "_stat",
7967 "stat32",
7968 "_stat32",
7969 "stat64",
7970 "_stat64",
7971 "_stati64",
7972 "if_nameindex",
7973 "usb_device",
7974 "sigaltstack",
7975 "sysinfo",
7976 "timeLocale",
7977 "tcp_debug",
7978 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007979 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007980 "timespec",
7981 "random_data",
7982 "drand48_data",
7983 "_IO_marker",
7984 "_IO_FILE",
7985 "lconv",
7986 "sched_param",
7987 "tm",
7988 "itimerspec",
7989 "_pthread_cleanup_buffer",
7990 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007991 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007992 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007993 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007994 "sigcontext",
7995 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007996 # Mac
7997 "_timex",
7998 "_class_t",
7999 "_category_t",
8000 "_class_ro_t",
8001 "_protocol_t",
8002 "_message_ref_t",
8003 "_super_message_ref_t",
8004 "_ivar_t",
8005 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008006);
8007
8008sub getCompileCmd($$$)
8009{
8010 my ($Path, $Opt, $Inc) = @_;
8011 my $GccCall = $GCC_PATH;
8012 if($Opt) {
8013 $GccCall .= " ".$Opt;
8014 }
8015 $GccCall .= " -x ";
8016 if($OSgroup eq "macos") {
8017 $GccCall .= "objective-";
8018 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008019
8020 if($EMERGENCY_MODE_48)
8021 { # workaround for GCC 4.8 (C only)
8022 $GccCall .= "c++";
8023 }
8024 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008025 { # compile as "C++" header
8026 # to obtain complete dump using GCC 4.0
8027 $GccCall .= "c++-header";
8028 }
8029 else
8030 { # compile as "C++" source
8031 # GCC 3.3 cannot compile headers
8032 $GccCall .= "c++";
8033 }
8034 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008035 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008036 $GccCall .= " ".$Opts;
8037 }
8038 # allow extra qualifications
8039 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008040 $GccCall .= " -fpermissive";
8041 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008042 if($NoStdInc)
8043 {
8044 $GccCall .= " -nostdinc";
8045 $GccCall .= " -nostdinc++";
8046 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008047 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008048 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008049 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008050 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008051 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008052 if($Inc)
8053 { # include paths
8054 $GccCall .= " ".$Inc;
8055 }
8056 return $GccCall;
8057}
8058
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008059sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008060{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008061 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008062 my %HeaderElems = (
8063 # Types
8064 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008065 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008066 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8067 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008068 "time.h" => ["time_t"],
8069 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008070 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8071 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008072 "stdbool.h" => ["_Bool"],
8073 "rpc/xdr.h" => ["bool_t"],
8074 "in_systm.h" => ["n_long", "n_short"],
8075 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008076 "arpa/inet.h" => ["fw_src", "ip_src"],
8077 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008078 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008079 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008080 );
8081 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008082 foreach (keys(%HeaderElems))
8083 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008084 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008085 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008086 }
8087 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008088 my %Types = ();
8089 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8090 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008091 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008092 }
8093 if(keys(%Types))
8094 {
8095 my %AddHeaders = ();
8096 foreach my $Type (keys(%Types))
8097 {
8098 if(my $Header = $AutoPreamble{$Type})
8099 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008100 if(my $Path = identifyHeader($Header, $LibVersion))
8101 {
8102 if(skipHeader($Path, $LibVersion)) {
8103 next;
8104 }
8105 $Path = path_format($Path, $OSgroup);
8106 $AddHeaders{$Path}{"Type"} = $Type;
8107 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008108 }
8109 }
8110 }
8111 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008112 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008113 }
8114 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008115 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008116}
8117
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008118sub checkCTags($)
8119{
8120 my $Path = $_[0];
8121 if(not $Path) {
8122 return;
8123 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008124 my $CTags = undef;
8125
8126 if($OSgroup eq "bsd")
8127 { # use ectags on BSD
8128 $CTags = get_CmdPath("ectags");
8129 if(not $CTags) {
8130 printMsg("WARNING", "can't find \'ectags\' program");
8131 }
8132 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008133 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008134 $CTags = get_CmdPath("ctags");
8135 }
8136 if(not $CTags)
8137 {
8138 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008139 return;
8140 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008141
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008142 if($OSgroup ne "linux")
8143 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008144 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8145 if($Info!~/exuberant/i)
8146 {
8147 printMsg("WARNING", "incompatible version of \'ctags\' program");
8148 return;
8149 }
8150 }
8151
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008152 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008153 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008154 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008155 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008156 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008157 open(CTAGS, "<", $Out);
8158 while(my $Line = <CTAGS>)
8159 {
8160 chomp($Line);
8161 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008162 if(defined $Intrinsic_Keywords{$Name})
8163 { # noise
8164 next;
8165 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008166 if($Type eq "n")
8167 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008168 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008169 next;
8170 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008171 if(index($Scpe, "struct:")==0) {
8172 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008173 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008174 if(index($Scpe, "namespace:")==0)
8175 {
8176 if($Scpe=~s/\Anamespace://) {
8177 $Name = $Scpe."::".$Name;
8178 }
8179 }
8180 $TUnit_NameSpaces{$Version}{$Name} = 1;
8181 }
8182 elsif($Type eq "p")
8183 {
8184 if(not $Scpe or index($Scpe, "namespace:")==0) {
8185 $TUnit_Funcs{$Version}{$Name} = 1;
8186 }
8187 }
8188 elsif($Type eq "x")
8189 {
8190 if(not $Scpe or index($Scpe, "namespace:")==0) {
8191 $TUnit_Vars{$Version}{$Name} = 1;
8192 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008193 }
8194 }
8195 close(CTAGS);
8196}
8197
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008198sub preChange($$)
8199{
8200 my ($HeaderPath, $IncStr) = @_;
8201
8202 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8203 my $Content = undef;
8204
8205 if($OStarget eq "windows"
8206 and get_dumpmachine($GCC_PATH)=~/mingw/i
8207 and $MinGWMode{$Version}!=-1)
8208 { # modify headers to compile by MinGW
8209 if(not $Content)
8210 { # preprocessing
8211 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8212 }
8213 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8214 { # __asm { ... }
8215 $MinGWMode{$Version}=1;
8216 }
8217 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8218 { # comments after preprocessing
8219 $MinGWMode{$Version}=1;
8220 }
8221 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8222 { # 0xffui8
8223 $MinGWMode{$Version}=1;
8224 }
8225
8226 if($MinGWMode{$Version}) {
8227 printMsg("INFO", "Using MinGW compatibility mode");
8228 }
8229 }
8230
8231 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8232 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8233 { # rename C++ keywords in C code
8234 # disable this code by -cpp-compatible option
8235 if(not $Content)
8236 { # preprocessing
8237 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8238 }
8239 my $RegExp_C = join("|", keys(%CppKeywords_C));
8240 my $RegExp_F = join("|", keys(%CppKeywords_F));
8241 my $RegExp_O = join("|", keys(%CppKeywords_O));
8242
8243 my $Detected = undef;
8244
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008245 while($Content=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*([\,\)\;\.\[]|\-\>|\:\s*\d))/$1$2c99_$3$4/g)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008246 { # MATCH:
8247 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008248 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008249 # unsigned private: 8;
8250 # DO NOT MATCH:
8251 # #pragma GCC visibility push(default)
8252 $CppMode{$Version} = 1;
8253 $Detected = "$1$2$3$4" if(not defined $Detected);
8254 }
8255 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8256 { # MATCH:
8257 # int delete(...);
8258 # int explicit(...);
8259 # DO NOT MATCH:
8260 # void operator delete(...)
8261 $CppMode{$Version} = 1;
8262 $Detected = "$1$2$3" if(not defined $Detected);
8263 }
8264 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8265 { # MATCH:
8266 # int bool;
8267 # DO NOT MATCH:
8268 # bool X;
8269 # return *this;
8270 # throw;
8271 $CppMode{$Version} = 1;
8272 $Detected = "$1$2$3" if(not defined $Detected);
8273 }
8274 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8275 { # MATCH:
8276 # int operator(...);
8277 # DO NOT MATCH:
8278 # int operator()(...);
8279 $CppMode{$Version} = 1;
8280 $Detected = "$1$2$3" if(not defined $Detected);
8281 }
8282 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8283 { # MATCH:
8284 # int foo(int operator);
8285 # int foo(int operator, int other);
8286 # DO NOT MATCH:
8287 # int operator,(...);
8288 $CppMode{$Version} = 1;
8289 $Detected = "$1$2$3" if(not defined $Detected);
8290 }
8291 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8292 { # MATCH:
8293 # int foo(gboolean *bool);
8294 # DO NOT MATCH:
8295 # void setTabEnabled(int index, bool);
8296 $CppMode{$Version} = 1;
8297 $Detected = "$1$2$3" if(not defined $Detected);
8298 }
8299 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8300 { # MATCH:
8301 # int foo(int* this);
8302 # int bar(int this);
8303 # int baz(int throw);
8304 # DO NOT MATCH:
8305 # foo(X, this);
8306 $CppMode{$Version} = 1;
8307 $Detected = "$1$2$3$4" if(not defined $Detected);
8308 }
8309 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8310 { # MATCH:
8311 # struct template {...};
8312 # extern template foo(...);
8313 $CppMode{$Version} = 1;
8314 $Detected = "$1$2" if(not defined $Detected);
8315 }
8316
8317 if($CppMode{$Version} == 1)
8318 {
8319 if($Debug)
8320 {
8321 $Detected=~s/\A\s+//g;
8322 printMsg("INFO", "Detected code: \"$Detected\"");
8323 }
8324 }
8325
8326 # remove typedef enum NAME NAME;
8327 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8328 my $N = 0;
8329 while($N<=$#FwdTypedefs-1)
8330 {
8331 my $S = $FwdTypedefs[$N];
8332 if($S eq $FwdTypedefs[$N+1])
8333 {
8334 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008335 $CppMode{$Version} = 1;
8336
8337 if($Debug) {
8338 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8339 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008340 }
8341 $N+=2;
8342 }
8343
8344 if($CppMode{$Version}==1) {
8345 printMsg("INFO", "Using C++ compatibility mode");
8346 }
8347 }
8348
8349 if($CppMode{$Version}==1
8350 or $MinGWMode{$Version}==1)
8351 {
8352 my $IPath = $TMP_DIR."/dump$Version.i";
8353 writeFile($IPath, $Content);
8354 return $IPath;
8355 }
8356
8357 return undef;
8358}
8359
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008360sub getDump()
8361{
8362 if(not $GCC_PATH) {
8363 exitStatus("Error", "internal error - GCC path is not set");
8364 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008365
8366 my @Headers = keys(%{$Registered_Headers{$Version}});
8367 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8368
8369 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8370
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008371 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008372 my $HeaderPath = $TmpHeaderPath;
8373
8374 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008375 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008376 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8377 {
8378 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008379 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008380 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008381 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008382 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8383 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008384 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008385 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008386 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008387 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8388 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8389 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008390 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008391 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008392
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008393 if($ExtraInfo)
8394 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008395 if($IncludeString) {
8396 writeFile($ExtraInfo."/include-string", $IncludeString);
8397 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008398 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8399 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008400
8401 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8402 {
8403 my $REDIR = "";
8404 foreach my $P1 (sort @Redirects) {
8405 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8406 }
8407 writeFile($ExtraInfo."/include-redirect", $REDIR);
8408 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008409 }
8410
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008411 if(not keys(%{$TargetHeaders{$Version}}))
8412 { # Target headers
8413 addTargetHeaders($Version);
8414 }
8415
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008416 # clean memory
8417 %RecursiveIncludes = ();
8418 %Header_Include_Prefix = ();
8419 %Header_Includes = ();
8420
8421 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008422 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008423 delete($Cache{"detect_header_includes"});
8424 delete($Cache{"selectSystemHeader"});
8425
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008426 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008427 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8428 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008429
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008430 if($ExtraInfo)
8431 { # extra information for other tools
8432 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8433 }
8434
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008435 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008436 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008437 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008438
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008439 if($COMMON_LANGUAGE{$Version} eq "C++") {
8440 checkCTags($Pre);
8441 }
8442
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008443 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8444 { # try to correct the preprocessor output
8445 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008446 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008447
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008448 if($COMMON_LANGUAGE{$Version} eq "C++")
8449 { # add classes and namespaces to the dump
8450 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008451 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008452 or $MinGWMode{$Version}==1) {
8453 $CHdump .= " -fpreprocessed";
8454 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008455 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008456 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008457 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008458 chdir($ORIG_DIR);
8459 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8460 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008461 my $Content = readFile($ClassDump);
8462 foreach my $ClassInfo (split(/\n\n/, $Content))
8463 {
8464 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8465 {
8466 my $CName = $1;
8467 next if($CName=~/\A(__|_objc_|_opaque_)/);
8468 $TUnit_NameSpaces{$Version}{$CName} = -1;
8469 if($CName=~/\A[\w:]+\Z/)
8470 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008471 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008472 }
8473 if($CName=~/(\w[\w:]*)::/)
8474 { # namespaces
8475 my $NS = $1;
8476 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8477 $TUnit_NameSpaces{$Version}{$NS} = 1;
8478 }
8479 }
8480 }
8481 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8482 { # read v-tables (advanced approach)
8483 my ($CName, $VTable) = ($1, $2);
8484 $ClassVTable_Content{$Version}{$CName} = $VTable;
8485 }
8486 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008487 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8488 { # add user-defined namespaces
8489 $TUnit_NameSpaces{$Version}{$NS} = 1;
8490 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008491 if($Debug)
8492 { # debug mode
8493 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008494 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008495 }
8496 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008497 }
8498
8499 # add namespaces and classes
8500 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8501 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008502 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008503 }
8504 # some GCC versions don't include class methods to the TU dump by default
8505 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008506 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008507 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8508 {
8509 next if($C_Structure{$CName});
8510 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008511 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008512 if(not $Force and $GCC_44
8513 and $OSgroup eq "linux")
8514 { # optimization for linux with GCC >= 4.4
8515 # disable this code by -force option
8516 if(index($CName, "::")!=-1)
8517 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008518 next;
8519 }
8520 }
8521 else
8522 {
8523 if($CName=~/\A(.+)::[^:]+\Z/
8524 and $TUnit_Classes{$Version}{$1})
8525 { # classes inside other classes
8526 next;
8527 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008528 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008529 if(defined $TUnit_Funcs{$Version}{$CName})
8530 { # the same name for a function and type
8531 next;
8532 }
8533 if(defined $TUnit_Vars{$Version}{$CName})
8534 { # the same name for a variable and type
8535 next;
8536 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008537 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8538 }
8539 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008540 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008541 }
8542 }
8543 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8544 # create TU dump
8545 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008546 if($UserLang eq "C") {
8547 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8548 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008549 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008550 or $MinGWMode{$Version}==1) {
8551 $TUdump .= " -fpreprocessed";
8552 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008553 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008554 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8555 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008556 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008557 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008558 if($?)
8559 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008560 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008561 { # try to recompile
8562 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008563 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008564 and index($Errors, "c99_")!=-1
8565 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008566 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008567 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008568
8569 if($Debug)
8570 {
8571 # printMsg("INFO", $Errors);
8572 }
8573
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008574 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008575 resetLogging($Version);
8576 $TMP_DIR = tempdir(CLEANUP=>1);
8577 return getDump();
8578 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008579 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008580 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008581 { # add auto preamble headers and try again
8582 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008583 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008584 foreach my $Num (0 .. $#Headers)
8585 {
8586 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008587 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8588 {
8589 push_U($Include_Preamble{$Version}, $Path);
8590 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008591 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008592 }
8593 resetLogging($Version);
8594 $TMP_DIR = tempdir(CLEANUP=>1);
8595 return getDump();
8596 }
8597 elsif($Cpp0xMode{$Version}!=-1
8598 and ($Errors=~/\Q-std=c++0x\E/
8599 or $Errors=~/is not a class or namespace/))
8600 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008601 if(check_gcc($GCC_PATH, "4.6"))
8602 {
8603 $Cpp0xMode{$Version}=-1;
8604 printMsg("INFO", "Enabling c++0x mode");
8605 resetLogging($Version);
8606 $TMP_DIR = tempdir(CLEANUP=>1);
8607 $CompilerOptions{$Version} .= " -std=c++0x";
8608 return getDump();
8609 }
8610 else {
8611 printMsg("WARNING", "Probably c++0x construction detected");
8612 }
8613
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008614 }
8615 elsif($MinGWMode{$Version}==1)
8616 { # disable MinGW mode and try again
8617 $MinGWMode{$Version}=-1;
8618 resetLogging($Version);
8619 $TMP_DIR = tempdir(CLEANUP=>1);
8620 return getDump();
8621 }
8622 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008623 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008624 else {
8625 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008626 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008627 printMsg("ERROR", "some errors occurred when compiling headers");
8628 printErrorLog($Version);
8629 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008630 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008631 }
8632 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008633 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008634 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008635
8636 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8637 return $TUs[0];
8638 }
8639 else
8640 {
8641 my $Msg = "can't compile header(s)";
8642 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8643 $Msg .= "\nDid you install G++?";
8644 }
8645 exitStatus("Cannot_Compile", $Msg);
8646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008647}
8648
8649sub cmd_file($)
8650{
8651 my $Path = $_[0];
8652 return "" if(not $Path or not -e $Path);
8653 if(my $CmdPath = get_CmdPath("file")) {
8654 return `$CmdPath -b \"$Path\"`;
8655 }
8656 return "";
8657}
8658
8659sub getIncString($$)
8660{
8661 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008662 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008663 my $String = "";
8664 foreach (@{$ArrRef}) {
8665 $String .= " ".inc_opt($_, $Style);
8666 }
8667 return $String;
8668}
8669
8670sub getIncPaths(@)
8671{
8672 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008673 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008674 if($INC_PATH_AUTODETECT{$Version})
8675 { # auto-detecting dependencies
8676 my %Includes = ();
8677 foreach my $HPath (@HeaderPaths)
8678 {
8679 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8680 {
8681 if($Skip_Include_Paths{$Version}{$Dir}) {
8682 next;
8683 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008684 if($SystemRoot)
8685 {
8686 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8687 next;
8688 }
8689 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008690 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008691 }
8692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008693 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008694 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008695 }
8696 }
8697 else
8698 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008699 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008700 }
8701 return \@IncPaths;
8702}
8703
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008704sub push_U($@)
8705{ # push unique
8706 if(my $Array = shift @_)
8707 {
8708 if(@_)
8709 {
8710 my %Exist = map {$_=>1} @{$Array};
8711 foreach my $Elem (@_)
8712 {
8713 if(not defined $Exist{$Elem})
8714 {
8715 push(@{$Array}, $Elem);
8716 $Exist{$Elem} = 1;
8717 }
8718 }
8719 }
8720 }
8721}
8722
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008723sub callPreprocessor($$$)
8724{
8725 my ($Path, $Inc, $LibVersion) = @_;
8726 return "" if(not $Path or not -f $Path);
8727 my $IncludeString=$Inc;
8728 if(not $Inc) {
8729 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8730 }
8731 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008732 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008733 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008734 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008735}
8736
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008737sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008738{ # native "find" is much faster than File::Find (~6x)
8739 # also the File::Find doesn't support --maxdepth N option
8740 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008741 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008742 return () if(not $Path or not -e $Path);
8743 if($OSgroup eq "windows")
8744 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008745 $Path = get_abs_path($Path);
8746 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008747 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008748 if($MaxDepth!=1) {
8749 $Cmd .= " /S";
8750 }
8751 if($Type eq "d") {
8752 $Cmd .= " /AD";
8753 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008754 elsif($Type eq "f") {
8755 $Cmd .= " /A-D";
8756 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008757 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008758 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008759 {
8760 if(not $UseRegex)
8761 { # FIXME: how to search file names in MS shell?
8762 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008763 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008764 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008765 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008766 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008767 }
8768 my @AbsPaths = ();
8769 foreach my $File (@Files)
8770 {
8771 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008772 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008773 }
8774 if($Type eq "f" and not -f $File)
8775 { # skip dirs
8776 next;
8777 }
8778 push(@AbsPaths, path_format($File, $OSgroup));
8779 }
8780 if($Type eq "d") {
8781 push(@AbsPaths, $Path);
8782 }
8783 return @AbsPaths;
8784 }
8785 else
8786 {
8787 my $FindCmd = get_CmdPath("find");
8788 if(not $FindCmd) {
8789 exitStatus("Not_Found", "can't find a \"find\" command");
8790 }
8791 $Path = get_abs_path($Path);
8792 if(-d $Path and -l $Path
8793 and $Path!~/\/\Z/)
8794 { # for directories that are symlinks
8795 $Path.="/";
8796 }
8797 my $Cmd = $FindCmd." \"$Path\"";
8798 if($MaxDepth) {
8799 $Cmd .= " -maxdepth $MaxDepth";
8800 }
8801 if($Type) {
8802 $Cmd .= " -type $Type";
8803 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008804 if($Name and not $UseRegex)
8805 { # wildcards
8806 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008807 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008808 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008809 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008810 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8811 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008812 my @Files = split(/\n/, $Res);
8813 if($Name and $UseRegex)
8814 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008815 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008816 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008817 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008818 }
8819}
8820
8821sub unpackDump($)
8822{
8823 my $Path = $_[0];
8824 return "" if(not $Path or not -e $Path);
8825 $Path = get_abs_path($Path);
8826 $Path = path_format($Path, $OSgroup);
8827 my ($Dir, $FileName) = separate_path($Path);
8828 my $UnpackDir = $TMP_DIR."/unpack";
8829 rmtree($UnpackDir);
8830 mkpath($UnpackDir);
8831 if($FileName=~s/\Q.zip\E\Z//g)
8832 { # *.zip
8833 my $UnzipCmd = get_CmdPath("unzip");
8834 if(not $UnzipCmd) {
8835 exitStatus("Not_Found", "can't find \"unzip\" command");
8836 }
8837 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008838 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008839 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008840 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008841 }
8842 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008843 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008844 if(not @Contents) {
8845 exitStatus("Error", "can't extract \'$Path\'");
8846 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008847 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008848 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008849 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008850 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008851 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008852 if($OSgroup eq "windows")
8853 { # -xvzf option is not implemented in tar.exe (2003)
8854 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8855 my $TarCmd = get_CmdPath("tar");
8856 if(not $TarCmd) {
8857 exitStatus("Not_Found", "can't find \"tar\" command");
8858 }
8859 my $GzipCmd = get_CmdPath("gzip");
8860 if(not $GzipCmd) {
8861 exitStatus("Not_Found", "can't find \"gzip\" command");
8862 }
8863 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008864 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008865 if($?) {
8866 exitStatus("Error", "can't extract \'$Path\'");
8867 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008868 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008869 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008870 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008871 }
8872 chdir($ORIG_DIR);
8873 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008874 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008875 if(not @Contents) {
8876 exitStatus("Error", "can't extract \'$Path\'");
8877 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008878 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008879 }
8880 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008881 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008882 my $TarCmd = get_CmdPath("tar");
8883 if(not $TarCmd) {
8884 exitStatus("Not_Found", "can't find \"tar\" command");
8885 }
8886 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008887 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008888 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008889 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008890 }
8891 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008892 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008893 if(not @Contents) {
8894 exitStatus("Error", "can't extract \'$Path\'");
8895 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008896 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008897 }
8898 }
8899}
8900
8901sub createArchive($$)
8902{
8903 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008904 if(not $To) {
8905 $To = ".";
8906 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008907 if(not $Path or not -e $Path
8908 or not -d $To) {
8909 return "";
8910 }
8911 my ($From, $Name) = separate_path($Path);
8912 if($OSgroup eq "windows")
8913 { # *.zip
8914 my $ZipCmd = get_CmdPath("zip");
8915 if(not $ZipCmd) {
8916 exitStatus("Not_Found", "can't find \"zip\"");
8917 }
8918 my $Pkg = $To."/".$Name.".zip";
8919 unlink($Pkg);
8920 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008921 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008922 if($?)
8923 { # cannot allocate memory (or other problems with "zip")
8924 unlink($Path);
8925 exitStatus("Error", "can't pack the ABI dump: ".$!);
8926 }
8927 chdir($ORIG_DIR);
8928 unlink($Path);
8929 return $Pkg;
8930 }
8931 else
8932 { # *.tar.gz
8933 my $TarCmd = get_CmdPath("tar");
8934 if(not $TarCmd) {
8935 exitStatus("Not_Found", "can't find \"tar\"");
8936 }
8937 my $GzipCmd = get_CmdPath("gzip");
8938 if(not $GzipCmd) {
8939 exitStatus("Not_Found", "can't find \"gzip\"");
8940 }
8941 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8942 unlink($Pkg);
8943 chdir($From);
8944 system($TarCmd, "-czf", $Pkg, $Name);
8945 if($?)
8946 { # cannot allocate memory (or other problems with "tar")
8947 unlink($Path);
8948 exitStatus("Error", "can't pack the ABI dump: ".$!);
8949 }
8950 chdir($ORIG_DIR);
8951 unlink($Path);
8952 return $To."/".$Name.".tar.gz";
8953 }
8954}
8955
8956sub is_header_file($)
8957{
8958 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8959 return $_[0];
8960 }
8961 return 0;
8962}
8963
8964sub is_not_header($)
8965{
8966 if($_[0]=~/\.\w+\Z/
8967 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8968 return 1;
8969 }
8970 return 0;
8971}
8972
8973sub is_header($$$)
8974{
8975 my ($Header, $UserDefined, $LibVersion) = @_;
8976 return 0 if(-d $Header);
8977 if(-f $Header) {
8978 $Header = get_abs_path($Header);
8979 }
8980 else
8981 {
8982 if(is_abs($Header))
8983 { # incorrect absolute path
8984 return 0;
8985 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008986 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008987 $Header = $HPath;
8988 }
8989 else
8990 { # can't find header
8991 return 0;
8992 }
8993 }
8994 if($Header=~/\.\w+\Z/)
8995 { # have an extension
8996 return is_header_file($Header);
8997 }
8998 else
8999 {
9000 if($UserDefined==2)
9001 { # specified on the command line
9002 if(cmd_file($Header)!~/HTML|XML/i) {
9003 return $Header;
9004 }
9005 }
9006 elsif($UserDefined)
9007 { # specified in the XML-descriptor
9008 # header file without an extension
9009 return $Header;
9010 }
9011 else
9012 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009013 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009014 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009015 { # !~/HTML|XML|shared|dynamic/i
9016 return $Header;
9017 }
9018 }
9019 }
9020 return 0;
9021}
9022
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009023sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009024{
9025 my $LibVersion = $_[0];
9026 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9027 {
9028 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009029 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009030
9031 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9032 detect_recursive_includes($RegHeader, $LibVersion);
9033 }
9034
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009035 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9036 {
9037 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009038
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009039 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009040 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9041 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009042 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009043 }
9044 }
9045 }
9046}
9047
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009048sub familiarDirs($$)
9049{
9050 my ($D1, $D2) = @_;
9051 if($D1 eq $D2) {
9052 return 1;
9053 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009054
9055 my $U1 = index($D1, "/usr/");
9056 my $U2 = index($D2, "/usr/");
9057
9058 if($U1==0 and $U2!=0) {
9059 return 0;
9060 }
9061
9062 if($U2==0 and $U1!=0) {
9063 return 0;
9064 }
9065
9066 if(index($D2, $D1."/")==0) {
9067 return 1;
9068 }
9069
9070 # /usr/include/DIR
9071 # /home/user/DIR
9072
9073 my $DL = get_depth($D1);
9074
9075 my @Dirs1 = ($D1);
9076 while($DL - get_depth($D1)<=2
9077 and get_depth($D1)>=4
9078 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9079 push(@Dirs1, $D1);
9080 }
9081
9082 my @Dirs2 = ($D2);
9083 while(get_depth($D2)>=4
9084 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9085 push(@Dirs2, $D2);
9086 }
9087
9088 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009089 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009090 foreach my $P2 (@Dirs2)
9091 {
9092
9093 if($P1 eq $P2) {
9094 return 1;
9095 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009096 }
9097 }
9098 return 0;
9099}
9100
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009101sub readHeaders($)
9102{
9103 $Version = $_[0];
9104 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9105 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009106 if($Debug)
9107 { # debug mode
9108 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009109 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009110 }
9111 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009112}
9113
9114sub prepareTypes($)
9115{
9116 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009117 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009118 { # support for old ABI dumps
9119 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009120 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009121 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009122 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9123 if($TName=~/\A(\w+)::(\w+)/) {
9124 my ($P1, $P2) = ($1, $2);
9125 if($P1 eq $P2) {
9126 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009127 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009128 else {
9129 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9130 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009131 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009132 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009133 }
9134 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009135 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009136 { # support for old ABI dumps
9137 # V < 2.5: array size == "number of elements"
9138 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009139 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009140 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009141 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009142 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009143 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009144 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009145 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009146 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009147 $Size *= $Base{"Size"};
9148 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009149 }
9150 else
9151 { # array[] is a pointer
9152 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009153 }
9154 }
9155 }
9156 }
9157 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009158 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009159 { # support for old ABI dumps
9160 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009161 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009162 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009163 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009164 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009165 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009166 my %Type = get_Type($TypeId, $LibVersion);
9167 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9168 my %Type2 = get_Type($TypeId_2, $V2);
9169 if($Type{"Size"} ne $Type2{"Size"}) {
9170 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009171 }
9172 }
9173 }
9174 }
9175}
9176
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009177sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009178{
9179 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009180
9181 if(not keys(%{$SymbolInfo{$LibVersion}}))
9182 { # check if input is valid
9183 if(not $ExtendedCheck and not $CheckObjectsOnly)
9184 {
9185 if($CheckHeadersOnly) {
9186 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9187 }
9188 else {
9189 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9190 }
9191 }
9192 }
9193
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009194 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009195 if(not checkDump(1, "2.10")
9196 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009197 { # different formats
9198 $Remangle = 1;
9199 }
9200 if($CheckHeadersOnly)
9201 { # different languages
9202 if($UserLang)
9203 { # --lang=LANG for both versions
9204 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9205 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9206 {
9207 if($UserLang eq "C++")
9208 { # remangle symbols
9209 $Remangle = 1;
9210 }
9211 elsif($UserLang eq "C")
9212 { # remove mangling
9213 $Remangle = -1;
9214 }
9215 }
9216 }
9217 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009218
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009219 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009220 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009221 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009222 { # support for old ABI dumps
9223 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9224 {
9225 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9226 {
9227 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9228 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009229 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009230 if(defined $DVal and $DVal ne "")
9231 {
9232 if($TName eq "char") {
9233 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9234 }
9235 elsif($TName eq "bool") {
9236 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9237 }
9238 }
9239 }
9240 }
9241 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009242 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009243 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009244 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9245 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009246 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009247 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9248 # + support for old ABI dumps
9249 next;
9250 }
9251 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009252 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009253 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009254 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009255 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009256
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009257 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009258 if(not checkDump(1, "2.12")
9259 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009260 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009261 if($ShortName eq "operator>>")
9262 {
9263 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9264 { # corrected mangling of operator>>
9265 $SRemangle = 1;
9266 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009267 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009268 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9269 {
9270 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9271 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9272 { # corrected mangling of const global data
9273 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9274 # and incorrectly mangled by old ACC versions
9275 $SRemangle = 1;
9276 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009277 }
9278 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009279 if(not $CheckHeadersOnly)
9280 { # support for old ABI dumps
9281 if(not checkDump(1, "2.17")
9282 or not checkDump(2, "2.17"))
9283 {
9284 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9285 {
9286 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9287 {
9288 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9289 {
9290 $MnglName = $ShortName;
9291 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9292 }
9293 }
9294 }
9295 }
9296 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009297 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009298 { # support for old ABI dumps: some symbols are not mangled in old dumps
9299 # mangle both sets of symbols (old and new)
9300 # NOTE: remangling all symbols by the same mangler
9301 if($MnglName=~/\A_ZN(V|)K/)
9302 { # mangling may be incorrect on old ABI dumps
9303 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009304 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009305 }
9306 if($MnglName=~/\A_ZN(K|)V/)
9307 { # mangling may be incorrect on old ABI dumps
9308 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009309 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009310 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009311 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9312 or (not $ClassID and $CheckHeadersOnly)
9313 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9314 { # support for old ABI dumps, GCC >= 4.0
9315 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009316 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009317 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009318 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009319 $MangledNames{$LibVersion}{$MnglName} = 1;
9320 }
9321 }
9322 }
9323 elsif($Remangle==-1)
9324 { # remove mangling
9325 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009326 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009327 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009328 if(not $MnglName) {
9329 next;
9330 }
9331 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9332 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009333 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9334
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009335 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009336 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009337 { # support for old dumps
9338 # add "Volatile" attribute
9339 if($MnglName=~/_Z(K|)V/) {
9340 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9341 }
9342 }
9343 # symbol and its symlink have same signatures
9344 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009345 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009346 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009347
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009348 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9349 {
9350 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9351 if($SymVer{$LibVersion}{$Alias}) {
9352 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9353 }
9354 }
9355
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009356 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009357 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009358 }
9359 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9360 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9361 }
9362 if($ExtendedCheck)
9363 { # --ext option
9364 addExtension($LibVersion);
9365 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009366
9367 # clean memory
9368 delete($SymbolInfo{$LibVersion});
9369
9370 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009371 { # detect allocable classes with public exported constructors
9372 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009373 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009374 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009375 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009376 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009377 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9378 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009379 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009380 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009381 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009382 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009383 $AllocableClass{$LibVersion}{$ClassName} = 1;
9384 }
9385 }
9386 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009387 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009388 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009389 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009390 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009391 if($CheckHeadersOnly)
9392 {
9393 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9394 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9395 { # all symbols except non-virtual inline
9396 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9397 }
9398 }
9399 else {
9400 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009401 }
9402 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009403 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009404 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009405 }
9406 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009407 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009408 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009409 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009410 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009411 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009412 if(defined $Base{"Type"}
9413 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009414 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009415 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009416 if($Name=~/<([^<>\s]+)>/)
9417 {
9418 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9419 $ReturnedClass{$LibVersion}{$Tid} = 1;
9420 }
9421 }
9422 else {
9423 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9424 }
9425 }
9426 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009427 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009428 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009429 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009430 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009431 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009432 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009433 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009434 if($Base{"Type"}=~/Struct|Class/)
9435 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009436 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009437 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9438 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009439 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009440 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009441 }
9442 }
9443 }
9444 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009445
9446 # mapping {short name => symbols}
9447 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009448 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009449 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009450 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009451 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009452 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009453 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009454 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009455 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9456 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009457 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009458 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009459 }
9460 }
9461 }
9462 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009463
9464 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009465 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009466 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009467 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009468 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009469 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9470 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009471 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009472 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009473 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009474 $ClassNames{$LibVersion}{$TName} = 1;
9475 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009476 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009477 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9478 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009479 }
9480 }
9481 }
9482 }
9483 }
9484}
9485
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009486sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009487{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009488 my ($Tid, $LibVersion) = @_;
9489 if(not $Tid) {
9490 return $Tid;
9491 }
9492
9493 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9494 {
9495 if($TName_Tid{$LibVersion}{$Name}) {
9496 return $TName_Tid{$LibVersion}{$Name};
9497 }
9498 }
9499
9500 return $Tid;
9501}
9502
9503sub register_SymbolUsage($$$)
9504{
9505 my ($InfoId, $UsedType, $LibVersion) = @_;
9506
9507 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9508 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9509 {
9510 register_TypeUsage($RTid, $UsedType, $LibVersion);
9511 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9512 }
9513 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9514 {
9515 register_TypeUsage($FCid, $UsedType, $LibVersion);
9516 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9517
9518 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9519 { # register "this" pointer
9520 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9521 }
9522 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9523 { # register "this" pointer (const method)
9524 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9525 }
9526 }
9527 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9528 {
9529 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9530 {
9531 register_TypeUsage($PTid, $UsedType, $LibVersion);
9532 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9533 }
9534 }
9535 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9536 {
9537 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9538 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9539 register_TypeUsage($TTid, $UsedType, $LibVersion);
9540 }
9541 }
9542}
9543
9544sub register_TypeUsage($$$)
9545{
9546 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009547 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009548 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009549 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009550 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009551 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009552 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009553 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009554
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009555 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009556 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009557 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009558 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009559 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009560 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9561 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9562 }
9563 }
9564
9565 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9566 {
9567 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009568 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009569 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009570 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9571 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009572 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009573 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9574 {
9575 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9576 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009577 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009578 }
9579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009580 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009581 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009582 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009583 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9584 {
9585 register_TypeUsage($MTid, $UsedType, $LibVersion);
9586 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009587 }
9588 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009589 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009590 or $TInfo{"Type"} eq "MethodPtr"
9591 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009592 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009593 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009594 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009595 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009596 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009597 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009598 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9599 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009600 }
9601 }
9602 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009603 if($TInfo{"Type"} eq "FieldPtr")
9604 {
9605 if(my $RTid = $TInfo{"Return"}) {
9606 register_TypeUsage($RTid, $UsedType, $LibVersion);
9607 }
9608 if(my $CTid = $TInfo{"Class"}) {
9609 register_TypeUsage($CTid, $UsedType, $LibVersion);
9610 }
9611 }
9612 if($TInfo{"Type"} eq "MethodPtr")
9613 {
9614 if(my $CTid = $TInfo{"Class"}) {
9615 register_TypeUsage($CTid, $UsedType, $LibVersion);
9616 }
9617 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009618 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009619 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009620 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009621 $UsedType->{$TypeId} = 1;
9622 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9623 {
9624 register_TypeUsage($BTid, $UsedType, $LibVersion);
9625 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9626 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009627 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009628 else
9629 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9630 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009631 }
9632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009633}
9634
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009635sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009636{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009637 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9638
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009639 if($Level eq "Dump")
9640 {
9641 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9642 { # TODO: check if this symbol is from
9643 # base classes of other target symbols
9644 return 1;
9645 }
9646 }
9647
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009648 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9649 { # stdc++ interfaces
9650 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009651 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009652
9653 my $Target = 0;
9654 if(my $Header = $SInfo->{"Header"}) {
9655 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9656 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009657 if($ExtendedCheck)
9658 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009659 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009660 $Target = 1;
9661 }
9662 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009663 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009664 {
9665 if($Target)
9666 {
9667 if($Level eq "Dump")
9668 { # dumped
9669 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009670 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009671 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009672 return 1;
9673 }
9674 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009675 else {
9676 return 1;
9677 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009678 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009679 elsif($Level eq "Source")
9680 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009681 return 1;
9682 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009683 elsif($Level eq "Binary")
9684 { # checked
9685 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9686 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9687 return 1;
9688 }
9689 }
9690 }
9691 }
9692 else
9693 { # library is available
9694 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9695 { # exported symbols
9696 return 1;
9697 }
9698 if($Level eq "Dump")
9699 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009700 if($BinaryOnly)
9701 {
9702 if($SInfo->{"Data"})
9703 {
9704 if($Target) {
9705 return 1;
9706 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009707 }
9708 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009709 else
9710 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009711 if($Target) {
9712 return 1;
9713 }
9714 }
9715 }
9716 elsif($Level eq "Source")
9717 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009718 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
9719 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009720 { # skip LOCAL symbols
9721 if($Target) {
9722 return 1;
9723 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009724 }
9725 }
9726 elsif($Level eq "Binary")
9727 { # checked
9728 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9729 {
9730 if($Target) {
9731 return 1;
9732 }
9733 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009734 }
9735 }
9736 return 0;
9737}
9738
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009739sub cleanDump($)
9740{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009741 my $LibVersion = $_[0];
9742 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9743 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009744 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9745 {
9746 delete($SymbolInfo{$LibVersion}{$InfoId});
9747 next;
9748 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009749 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009750 if(not $MnglName)
9751 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009752 delete($SymbolInfo{$LibVersion}{$InfoId});
9753 next;
9754 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009755 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009756 if(not $ShortName)
9757 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009758 delete($SymbolInfo{$LibVersion}{$InfoId});
9759 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009760 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009761 if($MnglName eq $ShortName)
9762 { # remove duplicate data
9763 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009764 }
9765 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9766 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9767 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009768 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9769 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9770 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009771 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009772 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009773 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009774 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009775 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9776 {
9777 delete($TypeInfo{$LibVersion}{$Tid});
9778 next;
9779 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009780 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009781 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009782 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009783 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9784 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9785 }
9786 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009787 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9788 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9789 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009790 }
9791}
9792
9793sub selectType($$)
9794{
9795 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009796
9797 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9798 {
9799 if(defined $TypeInfo{$LibVersion}{$Dupl})
9800 {
9801 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9802 { # duplicate
9803 return 0;
9804 }
9805 }
9806 }
9807
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009808 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9809 {
9810 if(not isBuiltIn($THeader))
9811 {
9812 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009813 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009814 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9815 {
9816 if(is_target_header($THeader, $LibVersion))
9817 { # from target headers
9818 if(not selfTypedef($Tid, $LibVersion)) {
9819 return 1;
9820 }
9821 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009822 }
9823 }
9824 }
9825 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009826 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009827}
9828
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009829sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009830{ # remove unused data types from the ABI dump
9831 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009832
9833 my %UsedType = ();
9834
9835 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009836 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009837 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009838 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009839 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009840 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009841 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009842 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009843 next;
9844 }
9845
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009846 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009847 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009848 if(selectType($Tid, $LibVersion))
9849 {
9850 my %Tree = ();
9851 register_TypeUsage($Tid, \%Tree, $LibVersion);
9852
9853 my $Tmpl = 0;
9854 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9855 {
9856 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9857 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9858 {
9859 $Tmpl = 1;
9860 last;
9861 }
9862 }
9863 if(not $Tmpl)
9864 {
9865 foreach (keys(%Tree)) {
9866 $UsedType{$_} = 1;
9867 }
9868 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009869 }
9870 }
9871 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009872
9873 my %Delete = ();
9874
9875 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009876 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009877 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009878 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009879 next;
9880 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009881
9882 if($Kind eq "Extra")
9883 {
9884 my %Tree = ();
9885 register_TypeUsage($Tid, \%Tree, $LibVersion);
9886
9887 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9888 {
9889 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9890 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9891 {
9892 $Delete{$Tid} = 1;
9893 last;
9894 }
9895 }
9896 }
9897 else
9898 {
9899 # remove type
9900 delete($TypeInfo{$LibVersion}{$Tid});
9901 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009902 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009903
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009904 if($Kind eq "Extra")
9905 { # remove duplicates
9906 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9907 {
9908 if($UsedType{$Tid})
9909 { # All & Extended
9910 next;
9911 }
9912
9913 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9914
9915 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9916 delete($TypeInfo{$LibVersion}{$Tid});
9917 }
9918 }
9919 }
9920
9921 foreach my $Tid (keys(%Delete))
9922 {
9923 delete($TypeInfo{$LibVersion}{$Tid});
9924 }
9925}
9926
9927sub check_Completeness($$)
9928{
9929 my ($Info, $LibVersion) = @_;
9930
9931 # data types
9932 if(defined $Info->{"Memb"})
9933 {
9934 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9935 {
9936 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9937 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9938 }
9939 }
9940 }
9941 if(defined $Info->{"Base"})
9942 {
9943 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9944 check_TypeInfo($Bid, $LibVersion);
9945 }
9946 }
9947 if(defined $Info->{"BaseType"}) {
9948 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9949 }
9950 if(defined $Info->{"TParam"})
9951 {
9952 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9953 {
9954 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9955 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9956 next;
9957 }
9958 if($TName eq "_BoolType") {
9959 next;
9960 }
9961 if($TName=~/\Asizeof\(/) {
9962 next;
9963 }
9964 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9965 check_TypeInfo($Tid, $LibVersion);
9966 }
9967 else
9968 {
9969 if(defined $Debug) {
9970 printMsg("WARNING", "missed type $TName");
9971 }
9972 }
9973 }
9974 }
9975
9976 # symbols
9977 if(defined $Info->{"Param"})
9978 {
9979 foreach my $Pos (keys(%{$Info->{"Param"}}))
9980 {
9981 if(defined $Info->{"Param"}{$Pos}{"type"}) {
9982 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
9983 }
9984 }
9985 }
9986 if(defined $Info->{"Return"}) {
9987 check_TypeInfo($Info->{"Return"}, $LibVersion);
9988 }
9989 if(defined $Info->{"Class"}) {
9990 check_TypeInfo($Info->{"Class"}, $LibVersion);
9991 }
9992}
9993
9994sub check_TypeInfo($$)
9995{
9996 my ($Tid, $LibVersion) = @_;
9997
9998 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
9999 return;
10000 }
10001 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10002
10003 if(defined $TypeInfo{$LibVersion}{$Tid})
10004 {
10005 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10006 printMsg("ERROR", "missed type name ($Tid)");
10007 }
10008 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10009 }
10010 else {
10011 printMsg("ERROR", "missed type id $Tid");
10012 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010013}
10014
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010015sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010016{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010017 my ($TypeId, $LibVersion) = @_;
10018 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010019 if($Type{"Type"} eq "Typedef")
10020 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010021 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010022 if($Base{"Type"}=~/Class|Struct/)
10023 {
10024 if($Type{"Name"} eq $Base{"Name"}) {
10025 return 1;
10026 }
10027 elsif($Type{"Name"}=~/::(\w+)\Z/)
10028 {
10029 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10030 { # QPointer<QWidget>::QPointer
10031 return 1;
10032 }
10033 }
10034 }
10035 }
10036 return 0;
10037}
10038
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010039sub addExtension($)
10040{
10041 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010042 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010043 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010044 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010045 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010046 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10047 $TName=~s/\A(struct|union|class|enum) //;
10048 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010049
10050 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10051 "Header" => "extended.h",
10052 "ShortName" => $Symbol,
10053 "MnglName" => $Symbol,
10054 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10055 );
10056
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010057 $ExtendedSymbols{$Symbol} = 1;
10058 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10059 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010060 }
10061 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010062 $ExtendedSymbols{"external_func_0"} = 1;
10063 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10064 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010065}
10066
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010067sub findMethod($$$)
10068{
10069 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010070 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010071 {
10072 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10073 return $VirtMethodInClass;
10074 }
10075 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10076 return $VirtMethodInBaseClasses;
10077 }
10078 }
10079 return "";
10080}
10081
10082sub findMethod_Class($$$)
10083{
10084 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010085 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010086 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10087 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10088 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10089 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10090 { # search for interface with the same parameters suffix (overridden)
10091 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10092 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010093 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10094 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010095 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10096 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010097 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10098 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10099 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10100 return $Candidate;
10101 }
10102 }
10103 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010104 else
10105 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010106 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10107 return $Candidate;
10108 }
10109 }
10110 }
10111 }
10112 return "";
10113}
10114
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010115sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010116{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010117 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010118 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010119 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010120 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10121 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010122 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010123 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010124 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010125 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10126 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010127 { # pure virtual D2-destructors are marked as "virt" in the dump
10128 # virtual D2-destructors are NOT marked as "virt" in the dump
10129 # both destructors are not presented in the v-table
10130 next;
10131 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010132 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010133 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10134 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010135 }
10136}
10137
10138sub registerOverriding($)
10139{
10140 my $LibVersion = $_[0];
10141 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010142 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010143 foreach my $ClassName (@Classes)
10144 {
10145 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10146 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010147 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10148 { # pure virtuals
10149 next;
10150 }
10151 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10152 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010153 {
10154 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10155 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10156 { # both overridden virtual methods
10157 # and implemented pure virtual methods
10158 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10159 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10160 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10161 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010162 }
10163 }
10164 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10165 delete($VirtualTable{$LibVersion}{$ClassName});
10166 }
10167 }
10168}
10169
10170sub setVirtFuncPositions($)
10171{
10172 my $LibVersion = $_[0];
10173 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10174 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010175 my ($Num, $Rel) = (1, 0);
10176
10177 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010178 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010179 if($UsedDump{$LibVersion}{"DWARF"}) {
10180 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10181 }
10182 else {
10183 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10184 }
10185 foreach my $VirtFunc (@Funcs)
10186 {
10187 if($UsedDump{$LibVersion}{"DWARF"}) {
10188 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10189 }
10190 else {
10191 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10192 }
10193
10194 # set relative positions
10195 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10196 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10197 { # relative position excluding added and removed virtual functions
10198 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10199 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10200 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010202 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010203 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010204 }
10205 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010206 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010207 {
10208 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010209 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010210 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010211 }
10212 }
10213}
10214
10215sub get_sub_classes($$$)
10216{
10217 my ($ClassId, $LibVersion, $Recursive) = @_;
10218 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10219 my @Subs = ();
10220 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10221 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010222 if($Recursive)
10223 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010224 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10225 push(@Subs, $SubSubId);
10226 }
10227 }
10228 push(@Subs, $SubId);
10229 }
10230 return @Subs;
10231}
10232
10233sub get_base_classes($$$)
10234{
10235 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010236 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010237 return () if(not defined $ClassType{"Base"});
10238 my @Bases = ();
10239 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10240 keys(%{$ClassType{"Base"}}))
10241 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010242 if($Recursive)
10243 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010244 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10245 push(@Bases, $SubBaseId);
10246 }
10247 }
10248 push(@Bases, $BaseId);
10249 }
10250 return @Bases;
10251}
10252
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010253sub getVTable_Model($$)
10254{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010255 my ($ClassId, $LibVersion) = @_;
10256 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10257 my @Elements = ();
10258 foreach my $BaseId (@Bases, $ClassId)
10259 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010260 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010261 {
10262 if(defined $VirtualTable{$LibVersion}{$BName})
10263 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010264 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10265 if($UsedDump{$LibVersion}{"DWARF"}) {
10266 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10267 }
10268 else {
10269 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10270 }
10271 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010272 push(@Elements, $VFunc);
10273 }
10274 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010275 }
10276 }
10277 return @Elements;
10278}
10279
10280sub getVShift($$)
10281{
10282 my ($ClassId, $LibVersion) = @_;
10283 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10284 my $VShift = 0;
10285 foreach my $BaseId (@Bases)
10286 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010287 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010288 {
10289 if(defined $VirtualTable{$LibVersion}{$BName}) {
10290 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010292 }
10293 }
10294 return $VShift;
10295}
10296
10297sub getShift($$)
10298{
10299 my ($ClassId, $LibVersion) = @_;
10300 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10301 my $Shift = 0;
10302 foreach my $BaseId (@Bases)
10303 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010304 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010305 {
10306 if($Size!=1)
10307 { # not empty base class
10308 $Shift+=$Size;
10309 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010310 }
10311 }
10312 return $Shift;
10313}
10314
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010315sub getVTable_Size($$)
10316{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010317 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010318 my $Size = 0;
10319 # three approaches
10320 if(not $Size)
10321 { # real size
10322 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10323 $Size = keys(%VTable);
10324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010325 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010326 if(not $Size)
10327 { # shared library symbol size
10328 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10329 $Size /= $WORD_SIZE{$LibVersion};
10330 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010331 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010332 if(not $Size)
10333 { # model size
10334 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10335 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10336 }
10337 }
10338 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010339}
10340
10341sub isCopyingClass($$)
10342{
10343 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010344 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010345}
10346
10347sub isLeafClass($$)
10348{
10349 my ($ClassId, $LibVersion) = @_;
10350 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10351}
10352
10353sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010354{ # check structured type for public fields
10355 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010356}
10357
10358sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010359{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010360 my ($TypePtr, $Skip, $Start, $End) = @_;
10361 return 0 if(not $TypePtr);
10362 if($End==-1) {
10363 $End = keys(%{$TypePtr->{"Memb"}})-1;
10364 }
10365 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10366 {
10367 if($Skip and $Skip->{$MemPos})
10368 { # skip removed/added fields
10369 next;
10370 }
10371 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10372 {
10373 if(isPublic($TypePtr, $MemPos)) {
10374 return ($MemPos+1);
10375 }
10376 }
10377 }
10378 return 0;
10379}
10380
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010381sub isReserved($)
10382{ # reserved fields == private
10383 my $MName = $_[0];
10384 if($MName=~/reserved|padding|f_spare/i) {
10385 return 1;
10386 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010387 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010388 return 1;
10389 }
10390 if($MName=~/(pad\d+)/i) {
10391 return 1;
10392 }
10393 return 0;
10394}
10395
10396sub isPublic($$)
10397{
10398 my ($TypePtr, $FieldPos) = @_;
10399 return 0 if(not $TypePtr);
10400 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10401 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10402 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10403 { # by name in C language
10404 # FIXME: add other methods to detect private members
10405 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10406 if($MName=~/priv|abidata|parent_object/i)
10407 { # C-styled private data
10408 return 0;
10409 }
10410 if(lc($MName) eq "abi")
10411 { # ABI information/reserved field
10412 return 0;
10413 }
10414 if(isReserved($MName))
10415 { # reserved fields
10416 return 0;
10417 }
10418 return 1;
10419 }
10420 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10421 { # by access in C++ language
10422 return 1;
10423 }
10424 return 0;
10425}
10426
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010427sub getVTable_Real($$)
10428{
10429 my ($ClassName, $LibVersion) = @_;
10430 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10431 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010432 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010433 if(defined $Type{"VTable"}) {
10434 return %{$Type{"VTable"}};
10435 }
10436 }
10437 return ();
10438}
10439
10440sub cmpVTables($)
10441{
10442 my $ClassName = $_[0];
10443 my $Res = cmpVTables_Real($ClassName, 1);
10444 if($Res==-1) {
10445 $Res = cmpVTables_Model($ClassName);
10446 }
10447 return $Res;
10448}
10449
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010450sub cmpVTables_Model($)
10451{
10452 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010453 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010454 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010455 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010456 return 1;
10457 }
10458 }
10459 return 0;
10460}
10461
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010462sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010463{
10464 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010465 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10466 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010467 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010468 my %VTable_Old = getVTable_Real($ClassName, 1);
10469 my %VTable_New = getVTable_Real($ClassName, 2);
10470 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010471 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010472 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010473 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010474 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010475 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10476 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010477 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010478 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010479 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010480 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010481 my $Entry1 = $VTable_Old{$Offset};
10482 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010483 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010484 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010485 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010486 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010487
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010488 $Entry1 = simpleVEntry($Entry1);
10489 $Entry2 = simpleVEntry($Entry2);
10490 if($Entry1 ne $Entry2)
10491 { # register as changed
10492 if($Entry1=~/::([^:]+)\Z/)
10493 {
10494 my $M1 = $1;
10495 if($Entry2=~/::([^:]+)\Z/)
10496 {
10497 my $M2 = $1;
10498 if($M1 eq $M2)
10499 { # overridden
10500 next;
10501 }
10502 }
10503 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010504 if(differentDumps("G"))
10505 {
10506 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10507 {
10508 # GCC 4.6.1: -0x00000000000000010
10509 # GCC 4.7.0: -16
10510 next;
10511 }
10512 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010513 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010514 }
10515 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010516 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010517}
10518
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010519sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010520{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010521 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010522 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10523 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010524 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010525 { # already registered
10526 next;
10527 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010528 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010529 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010530 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010531 foreach my $Symbol (@Affected)
10532 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010533 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010534 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010535 "Target"=>$ClassName);
10536 }
10537 }
10538 }
10539}
10540
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010541sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010542{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010543 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010544 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010545 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010546 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010547 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010548 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010549 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010550 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010551 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010552 if($TName_Tid{1}{$ClassName}
10553 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010554 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010555 if(defined $CompleteSignature{1}{$Symbol}
10556 and $CompleteSignature{1}{$Symbol}{"Virt"})
10557 { # override some method in v.1
10558 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010559 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010560 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010561 }
10562 }
10563 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010564 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010565 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010566 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010567 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010568 if($TName_Tid{2}{$ClassName}
10569 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010570 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010571 if(defined $CompleteSignature{2}{$Symbol}
10572 and $CompleteSignature{2}{$Symbol}{"Virt"})
10573 { # override some method in v.2
10574 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010575 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010576 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010577 }
10578 }
10579 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010580 if($Level eq "Binary")
10581 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010582 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010583 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10584 { # check replacements, including pure virtual methods
10585 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10586 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010587 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010588 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10589 if($AddedPos==$RemovedPos)
10590 {
10591 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10592 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10593 last; # other methods will be reported as "added" or "removed"
10594 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010595 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010596 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10597 {
10598 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10599 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010600 next;
10601 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010602 my $ProblemType = "Virtual_Replacement";
10603 my @Affected = ($RemovedVFunc);
10604 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10605 { # pure methods
10606 if(not isUsedClass($ClassId, 1, $Level))
10607 { # not a parameter of some exported method
10608 next;
10609 }
10610 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010611
10612 # affected all methods (both virtual and non-virtual ones)
10613 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10614 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010615 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010616 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010617 foreach my $AffectedInt (@Affected)
10618 {
10619 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10620 { # affected exported methods only
10621 next;
10622 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010623 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10624 next;
10625 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010626 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10627 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010628 "Target"=>get_Signature($AddedVFunc, 2),
10629 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10630 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010631 }
10632 }
10633 }
10634 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010635 if(not checkDump(1, "2.0")
10636 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010637 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010638 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010639 return;
10640 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010641 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010642 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010643 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010644 next if(not $ClassId_Old);
10645 if(not isCreatable($ClassId_Old, 1))
10646 { # skip classes without public constructors (including auto-generated)
10647 # example: class has only a private exported or private inline constructor
10648 next;
10649 }
10650 if($ClassName=~/>/)
10651 { # skip affected template instances
10652 next;
10653 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010654 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010655 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010656 if(not $ClassId_New) {
10657 next;
10658 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010659 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010660 if($Class_New{"Type"}!~/Class|Struct/)
10661 { # became typedef
10662 if($Level eq "Binary") {
10663 next;
10664 }
10665 if($Level eq "Source")
10666 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010667 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010668 if($Class_New{"Type"}!~/Class|Struct/) {
10669 next;
10670 }
10671 $ClassId_New = $Class_New{"Tid"};
10672 }
10673 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010674
10675 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10676 { # incomplete info in the ABI dump
10677 next;
10678 }
10679
10680
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010681 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10682 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 +040010683
10684 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10685 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10686
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010687 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010688 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10689 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010690 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10691 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010692 my $Shift_Old = getShift($ClassId_Old, 1);
10693 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010694 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010695 my ($Added, $Removed) = (0, 0);
10696 my @StableBases_Old = ();
10697 foreach my $BaseId (@Bases_Old)
10698 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010699 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010700 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010701 push(@StableBases_Old, $BaseId);
10702 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010703 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010704 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010705 { # removed base
10706 # excluding namespace::SomeClass to SomeClass renaming
10707 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010708 if($Level eq "Binary")
10709 { # Binary-level
10710 if($Shift_Old ne $Shift_New)
10711 { # affected fields
10712 if(havePubFields(\%Class_Old)) {
10713 $ProblemKind .= "_And_Shift";
10714 }
10715 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10716 $ProblemKind .= "_And_Size";
10717 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010718 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010719 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10720 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010721 { # affected v-table
10722 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010723 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010724 }
10725 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010726 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010727 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10728 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010729 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10730 {
10731 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10732 if($ProblemKind=~/VTable/) {
10733 $VTableChanged_M{$SubName}=1;
10734 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010735 }
10736 }
10737 foreach my $Interface (@Affected)
10738 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010739 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10740 next;
10741 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010742 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010743 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010744 "Target"=>$BaseName,
10745 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10746 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10747 "Shift"=>abs($Shift_New-$Shift_Old) );
10748 }
10749 $Removed+=1;
10750 }
10751 }
10752 my @StableBases_New = ();
10753 foreach my $BaseId (@Bases_New)
10754 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010755 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010756 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010757 push(@StableBases_New, $BaseId);
10758 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010759 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010760 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010761 { # added base
10762 # excluding namespace::SomeClass to SomeClass renaming
10763 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010764 if($Level eq "Binary")
10765 { # Binary-level
10766 if($Shift_Old ne $Shift_New)
10767 { # affected fields
10768 if(havePubFields(\%Class_Old)) {
10769 $ProblemKind .= "_And_Shift";
10770 }
10771 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10772 $ProblemKind .= "_And_Size";
10773 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010774 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010775 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10776 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010777 { # affected v-table
10778 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010779 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010780 }
10781 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010782 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010783 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10784 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010785 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10786 {
10787 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10788 if($ProblemKind=~/VTable/) {
10789 $VTableChanged_M{$SubName}=1;
10790 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010791 }
10792 }
10793 foreach my $Interface (@Affected)
10794 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010795 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10796 next;
10797 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010798 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010799 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010800 "Target"=>$BaseName,
10801 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10802 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10803 "Shift"=>abs($Shift_New-$Shift_Old) );
10804 }
10805 $Added+=1;
10806 }
10807 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010808 if($Level eq "Binary")
10809 { # Binary-level
10810 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010811 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10812 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010813 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010814 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010815 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010816 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010817 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010818 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10819 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010820 if($NewPos!=$OldPos)
10821 { # changed position of the base class
10822 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010823 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010824 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10825 next;
10826 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010827 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10828 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010829 "Target"=>$BaseName,
10830 "Old_Value"=>$OldPos-1,
10831 "New_Value"=>$NewPos-1 );
10832 }
10833 }
10834 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10835 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10836 { # became non-virtual base
10837 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10838 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010839 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10840 next;
10841 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010842 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10843 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010844 "Target"=>$BaseName );
10845 }
10846 }
10847 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10848 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10849 { # became virtual base
10850 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10851 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010852 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10853 next;
10854 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010855 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10856 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010857 "Target"=>$BaseName );
10858 }
10859 }
10860 }
10861 }
10862 # detect size changes in base classes
10863 if($Shift_Old!=$Shift_New)
10864 { # size of allocable class
10865 foreach my $BaseId (@StableBases_Old)
10866 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010867 my %BaseType = get_Type($BaseId, 1);
10868 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010869 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010870 if($Size_Old ne $Size_New
10871 and $Size_Old and $Size_New)
10872 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010873 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010874 if(isCopyingClass($BaseId, 1)) {
10875 $ProblemType = "Size_Of_Copying_Class";
10876 }
10877 elsif($AllocableClass{1}{$BaseType{"Name"}})
10878 {
10879 if($Size_New>$Size_Old)
10880 { # increased size
10881 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010882 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010883 else
10884 { # decreased size
10885 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10886 if(not havePubFields(\%Class_Old))
10887 { # affected class has no public members
10888 next;
10889 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010890 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010891 }
10892 next if(not $ProblemType);
10893 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10894 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010895 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10896 next;
10897 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010898 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10899 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010900 "Target"=>$BaseType{"Name"},
10901 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10902 "New_Size"=>$Size_New*$BYTE_SIZE );
10903 }
10904 }
10905 }
10906 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010907 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010908 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010909 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010910 { # compare virtual tables size in base classes
10911 my $VShift_Old = getVShift($ClassId_Old, 1);
10912 my $VShift_New = getVShift($ClassId_New, 2);
10913 if($VShift_Old ne $VShift_New)
10914 { # changes in the base class or changes in the list of base classes
10915 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10916 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10917 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010918 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010919 foreach my $BaseId (@AllBases_Old)
10920 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010921 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010922 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010923 { # lost base
10924 next;
10925 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010926 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10927 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010928 if($VSize_Old!=$VSize_New)
10929 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010930 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010931 { # TODO: affected non-virtual methods?
10932 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010933 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10934 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010935 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010936 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010937 { # skip interfaces that have not changed the absolute virtual position
10938 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010939 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010940 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10941 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010942 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010943 $VTableChanged_M{$BaseType{"Name"}} = 1;
10944 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010945 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10946 { # the reason of the layout change: added virtual functions
10947 next if($VirtualReplacement{$VirtFunc});
10948 my $ProblemType = "Added_Virtual_Method";
10949 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10950 $ProblemType = "Added_Pure_Virtual_Method";
10951 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010952 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010953 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010954 "Target"=>get_Signature($VirtFunc, 2) );
10955 }
10956 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10957 { # the reason of the layout change: removed virtual functions
10958 next if($VirtualReplacement{$VirtFunc});
10959 my $ProblemType = "Removed_Virtual_Method";
10960 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10961 $ProblemType = "Removed_Pure_Virtual_Method";
10962 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010963 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010964 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010965 "Target"=>get_Signature($VirtFunc, 1) );
10966 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010967 }
10968 }
10969 }
10970 }
10971 }
10972 }
10973 }
10974}
10975
10976sub isCreatable($$)
10977{
10978 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010979 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010980 or isCopyingClass($ClassId, $LibVersion)) {
10981 return 1;
10982 }
10983 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10984 { # Fix for incomplete data: if this class has
10985 # a base class then it should also has a constructor
10986 return 1;
10987 }
10988 if($ReturnedClass{$LibVersion}{$ClassId})
10989 { # returned by some method of this class
10990 # or any other class
10991 return 1;
10992 }
10993 return 0;
10994}
10995
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010996sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010997{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010998 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010999 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11000 { # parameter of some exported method
11001 return 1;
11002 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011003 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11004 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011005 { # method from target class
11006 return 1;
11007 }
11008 return 0;
11009}
11010
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011011sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011012{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011013 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011014 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011015 # - virtual
11016 # - pure-virtual
11017 # - non-virtual
11018 if($CompleteSignature{1}{$Interface}{"Data"})
11019 { # global data is not affected
11020 return;
11021 }
11022 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011023 if(not $Class_Id) {
11024 return;
11025 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011026 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011027 if(cmpVTables_Real($CName, 1)==0)
11028 { # no changes
11029 return;
11030 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011031 $CheckedTypes{$Level}{$CName} = 1;
11032 if($Level eq "Binary")
11033 { # Binary-level
11034 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11035 and not isUsedClass($Class_Id, 1, $Level))
11036 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011037 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011038 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011039 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011040 }
11041 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11042 {
11043 if(defined $VirtualTable{2}{$CName}{$Func}
11044 and defined $CompleteSignature{2}{$Func})
11045 {
11046 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11047 and $CompleteSignature{2}{$Func}{"PureVirt"})
11048 { # became pure virtual
11049 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11050 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011051 "Target"=>get_Signature_M($Func, 1) );
11052 $VTableChanged_M{$CName} = 1;
11053 }
11054 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11055 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11056 { # became non-pure virtual
11057 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11058 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011059 "Target"=>get_Signature_M($Func, 1) );
11060 $VTableChanged_M{$CName} = 1;
11061 }
11062 }
11063 }
11064 if($Level eq "Binary")
11065 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011066 # check virtual table structure
11067 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11068 {
11069 next if($Interface eq $AddedVFunc);
11070 next if($VirtualReplacement{$AddedVFunc});
11071 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11072 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11073 { # pure virtual methods affect all others (virtual and non-virtual)
11074 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011075 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011076 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011077 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011078 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011079 elsif(not defined $VirtualTable{1}{$CName}
11080 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011081 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011082 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011083 { # became polymorphous class, added v-table pointer
11084 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011085 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011086 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011087 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011088 }
11089 else
11090 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011091 my $VSize_Old = getVTable_Size($CName, 1);
11092 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011093 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011094 if(isCopyingClass($Class_Id, 1))
11095 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11096 my $ProblemType = "Added_Virtual_Method";
11097 if(isLeafClass($Class_Id, 1)) {
11098 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11099 }
11100 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11101 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011102 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011103 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011104 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011105 else
11106 {
11107 my $ProblemType = "Added_Virtual_Method";
11108 if(isLeafClass($Class_Id, 1)) {
11109 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11110 }
11111 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11112 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011113 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011114 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011115 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011116 }
11117 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011118 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11119 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011120 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011121 if(defined $VirtualTable{1}{$CName}
11122 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011123 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011124 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11125 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011126
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011127 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011128 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011129 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11130 foreach my $ASymbol (@Affected)
11131 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011132 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11133 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011134 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011135 next;
11136 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011137 }
11138 $CheckedSymbols{$Level}{$ASymbol} = 1;
11139 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11140 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011141 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011142 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011143 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011144 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011145 }
11146 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011147 else {
11148 # safe
11149 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011150 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011151 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11152 {
11153 next if($VirtualReplacement{$RemovedVFunc});
11154 if($RemovedVFunc eq $Interface
11155 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11156 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011157 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011158 next;
11159 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011160 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011161 { # became non-polymorphous class, removed v-table pointer
11162 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11163 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011164 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011165 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011166 }
11167 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11168 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11169 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011170 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011171 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011172 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11173 next;
11174 }
11175 my $VPos_New = -1;
11176 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011177 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011178 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11179 }
11180 else
11181 {
11182 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011183 next;
11184 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011185 }
11186 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11187 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11188 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11189 {
11190 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11191 foreach my $ASymbol (@Affected)
11192 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011193 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11194 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011195 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011196 next;
11197 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011198 }
11199 my $ProblemType = "Removed_Virtual_Method";
11200 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11201 $ProblemType = "Removed_Pure_Virtual_Method";
11202 }
11203 $CheckedSymbols{$Level}{$ASymbol} = 1;
11204 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11205 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011206 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011207 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011208 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011209 }
11210 }
11211 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011212 }
11213 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011214 else
11215 { # Source-level
11216 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011217 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011218 next if($Interface eq $AddedVFunc);
11219 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011220 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011221 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11222 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011223 "Target"=>get_Signature($AddedVFunc, 2) );
11224 }
11225 }
11226 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11227 {
11228 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11229 {
11230 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11231 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011232 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011233 }
11234 }
11235 }
11236}
11237
11238sub find_MemberPair_Pos_byName($$)
11239{
11240 my ($Member_Name, $Pair_Type) = @_;
11241 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11242 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11243 {
11244 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11245 {
11246 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11247 $Name=~s/\A[_]+|[_]+\Z//g;
11248 if($Name eq $Member_Name) {
11249 return $MemberPair_Pos;
11250 }
11251 }
11252 }
11253 return "lost";
11254}
11255
11256sub find_MemberPair_Pos_byVal($$)
11257{
11258 my ($Member_Value, $Pair_Type) = @_;
11259 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11260 {
11261 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11262 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11263 return $MemberPair_Pos;
11264 }
11265 }
11266 return "lost";
11267}
11268
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011269sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011270{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011271 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011272 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011273 if( $_->{"T1"} eq $_[0]
11274 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011275 {
11276 return 1;
11277 }
11278 }
11279 return 0;
11280}
11281
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011282sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011283{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011284 my %IDs = (
11285 "T1" => $_[0],
11286 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011287 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011288 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011289}
11290
11291sub isRenamed($$$$$)
11292{
11293 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11294 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11295 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011296 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011297 if(not defined $Type2->{"Memb"}{$MemPos}) {
11298 return "";
11299 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011300 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011301 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011302
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011303 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11304 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011305 if($MemberPair_Pos_Rev eq "lost")
11306 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011307 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11308 { # base type match
11309 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011310 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011311 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11312 { # exact type match
11313 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011314 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011315 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11316 { # size match
11317 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011318 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011319 if(isReserved($Pair_Name))
11320 { # reserved fields
11321 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011322 }
11323 }
11324 return "";
11325}
11326
11327sub isLastElem($$)
11328{
11329 my ($Pos, $TypeRef) = @_;
11330 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11331 if($Name=~/last|count|max|total/i)
11332 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11333 return 1;
11334 }
11335 elsif($Name=~/END|NLIMITS\Z/)
11336 { # __RLIMIT_NLIMITS
11337 return 1;
11338 }
11339 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11340 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11341 { # NImageFormats, NColorRoles
11342 return 1;
11343 }
11344 return 0;
11345}
11346
11347sub nonComparable($$)
11348{
11349 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011350
11351 my $N1 = $T1->{"Name"};
11352 my $N2 = $T2->{"Name"};
11353
11354 $N1=~s/\A(struct|union|enum) //;
11355 $N2=~s/\A(struct|union|enum) //;
11356
11357 if($N1 ne $N2
11358 and not isAnon($N1)
11359 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011360 { # different names
11361 if($T1->{"Type"} ne "Pointer"
11362 or $T2->{"Type"} ne "Pointer")
11363 { # compare base types
11364 return 1;
11365 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011366 if($N1!~/\Avoid\s*\*/
11367 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011368 {
11369 return 1;
11370 }
11371 }
11372 elsif($T1->{"Type"} ne $T2->{"Type"})
11373 { # different types
11374 if($T1->{"Type"} eq "Class"
11375 and $T2->{"Type"} eq "Struct")
11376 { # "class" to "struct"
11377 return 0;
11378 }
11379 elsif($T2->{"Type"} eq "Class"
11380 and $T1->{"Type"} eq "Struct")
11381 { # "struct" to "class"
11382 return 0;
11383 }
11384 else
11385 { # "class" to "enum"
11386 # "union" to "class"
11387 # ...
11388 return 1;
11389 }
11390 }
11391 return 0;
11392}
11393
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011394sub isOpaque($)
11395{
11396 my $T = $_[0];
11397 if(not defined $T->{"Memb"})
11398 {
11399 return 1;
11400 }
11401 return 0;
11402}
11403
11404sub removeVPtr($)
11405{ # support for old ABI dumps
11406 my $TPtr = $_[0];
11407 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11408 if($#Pos>=1)
11409 {
11410 foreach my $Pos (0 .. $#Pos-1)
11411 {
11412 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11413 }
11414 delete($TPtr->{"Memb"}{$#Pos});
11415 }
11416}
11417
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011418sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011419{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011420 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011421 return {} if(not $Type1_Id or not $Type2_Id);
11422
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011423 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011424 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011425 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011426 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011427
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011428 my %Type1 = get_Type($Type1_Id, 1);
11429 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011430 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011431 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011432 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011433
11434 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011435 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11436 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011437
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011438 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11439
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011440 my %SubProblems = ();
11441
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011442 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11443 {
11444 if($Type1_Pure{"Type"}=~/Struct|Union/
11445 and $Type2_Pure{"Type"}=~/Struct|Union/)
11446 {
11447 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11448 {
11449 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11450 "Target"=>$Type1_Pure{"Name"},
11451 "Type_Name"=>$Type1_Pure{"Name"} );
11452
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011453 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011454 }
11455 }
11456 }
11457
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011458 if(not $Type1_Pure{"Size"}
11459 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011460 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011461 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11462 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11463 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011464 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011465 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011466 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011467 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011468 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011469 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011470 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011471 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11472 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11473 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011474
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011475 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11476 { # support for old ABI dumps
11477 # _vptr field added in 3.0
11478 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11479 {
11480 if(defined $Type2_Pure{"Memb"}
11481 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11482 {
11483 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11484 delete($Type2_Pure{"Memb"}{0});
11485 }
11486 else {
11487 removeVPtr(\%Type2_Pure);
11488 }
11489 }
11490 }
11491 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11492 {
11493 if(defined $Type1_Pure{"Memb"}
11494 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11495 {
11496 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11497 delete($Type1_Pure{"Memb"}{0});
11498 }
11499 else {
11500 removeVPtr(\%Type1_Pure);
11501 }
11502 }
11503 }
11504 }
11505
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011506 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11507 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011508
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011509 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011510 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11511 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011512 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011513 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11514 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011515 if($Base_1{"Name"} ne $Base_2{"Name"})
11516 {
11517 if(differentDumps("G")
11518 or differentDumps("V"))
11519 { # different GCC versions or different dumps
11520 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11521 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11522 # std::__va_list and __va_list
11523 $Base_1{"Name"}=~s/\A(\w+::)+//;
11524 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011525 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11526 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011527 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011528 }
11529 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11530 and $Base_1{"Name"} ne $Base_2{"Name"})
11531 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011532 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011533 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011534 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011535 {
11536 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11537 "Target"=>$Typedef_1{"Name"},
11538 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011539 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11540 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11541 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011542 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11543 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011544 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011545 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011546 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11547 {
11548 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11549 "Target"=>$Typedef_1{"Name"},
11550 "Type_Name"=>$Typedef_1{"Name"},
11551 "Old_Value"=>$Base_1{"Name"},
11552 "New_Value"=>$Base_2{"Name"} );
11553 }
11554 else
11555 {
11556 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11557 "Target"=>$Typedef_1{"Name"},
11558 "Type_Name"=>$Typedef_1{"Name"},
11559 "Old_Value"=>$Base_1{"Name"},
11560 "New_Value"=>$Base_2{"Name"} );
11561 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011562 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011563 }
11564 }
11565 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11566 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011567 my $TT1 = $Type1_Pure{"Type"};
11568 my $TT2 = $Type2_Pure{"Type"};
11569
11570 if($TT1 ne $TT2
11571 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011572 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011573 my $Short1 = $Type1_Pure{"Name"};
11574 my $Short2 = $Type2_Pure{"Name"};
11575
11576 $Short1=~s/\A\Q$TT1\E //ig;
11577 $Short2=~s/\A\Q$TT2\E //ig;
11578
11579 if($Short1 eq $Short2)
11580 {
11581 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11582 "Target"=>$Type1_Pure{"Name"},
11583 "Type_Name"=>$Type1_Pure{"Name"},
11584 "Old_Value"=>lc($Type1_Pure{"Type"}),
11585 "New_Value"=>lc($Type2_Pure{"Type"}) );
11586 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011587 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011588 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011589 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011590 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011591 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11592 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11593 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11594 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011595 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011596 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011597 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011598 {
11599 my $ProblemKind = "DataType_Size";
11600 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011601 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011602 {
11603 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11604 $ProblemKind = "Size_Of_Copying_Class";
11605 }
11606 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11607 {
11608 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11609 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11610 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011611 else
11612 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011613 # descreased size of allocable class
11614 # it has no special effects
11615 }
11616 }
11617 }
11618 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11619 "Target"=>$Type1_Pure{"Name"},
11620 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011621 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011622 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011623 }
11624 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011625 if(defined $Type1_Pure{"BaseType"}
11626 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011627 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011628 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11629 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011630 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011631 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11632 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011633 }
11634 }
11635 }
11636 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11637 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11638 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11639 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11640 { # detect removed and renamed fields
11641 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11642 next if(not $Member_Name);
11643 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);
11644 if($MemberPair_Pos eq "lost")
11645 {
11646 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11647 {
11648 if(isUnnamed($Member_Name))
11649 { # support for old-version dumps
11650 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011651 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011652 next;
11653 }
11654 }
11655 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11656 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011657 $RenamedField{$Member_Pos} = $RenamedTo;
11658 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011659 }
11660 else
11661 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011662 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011663 }
11664 }
11665 elsif($Type1_Pure{"Type"} eq "Enum")
11666 {
11667 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11668 next if($Member_Value1 eq "");
11669 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11670 if($MemberPair_Pos ne "lost")
11671 { # renamed
11672 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11673 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11674 if($MemberPair_Pos_Rev eq "lost")
11675 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011676 $RenamedField{$Member_Pos} = $RenamedTo;
11677 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011678 }
11679 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011680 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011681 }
11682 }
11683 else
11684 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011685 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011686 }
11687 }
11688 }
11689 else
11690 { # related
11691 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11692 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11693 }
11694 }
11695 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11696 { # detect added fields
11697 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11698 next if(not $Member_Name);
11699 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);
11700 if($MemberPair_Pos eq "lost")
11701 {
11702 if(isUnnamed($Member_Name))
11703 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011704 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011705 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011706 next;
11707 }
11708 }
11709 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11710 {
11711 if(not $RenamedField_Rev{$Member_Pos})
11712 { # added
11713 $AddedField{$Member_Pos}=1;
11714 }
11715 }
11716 }
11717 }
11718 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11719 { # detect moved fields
11720 my (%RelPos, %RelPosName, %AbsPos) = ();
11721 my $Pos = 0;
11722 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11723 { # relative positions in 1st version
11724 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11725 next if(not $Member_Name);
11726 if(not $RemovedField{$Member_Pos})
11727 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011728 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011729 $RelPosName{1}{$Pos} = $Member_Name;
11730 $AbsPos{1}{$Pos++} = $Member_Pos;
11731 }
11732 }
11733 $Pos = 0;
11734 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11735 { # relative positions in 2nd version
11736 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11737 next if(not $Member_Name);
11738 if(not $AddedField{$Member_Pos})
11739 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011740 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011741 $RelPosName{2}{$Pos} = $Member_Name;
11742 $AbsPos{2}{$Pos++} = $Member_Pos;
11743 }
11744 }
11745 foreach my $Member_Name (keys(%{$RelPos{1}}))
11746 {
11747 my $RPos1 = $RelPos{1}{$Member_Name};
11748 my $AbsPos1 = $NameToPosA{$Member_Name};
11749 my $Member_Name2 = $Member_Name;
11750 if(my $RenamedTo = $RenamedField{$AbsPos1})
11751 { # renamed
11752 $Member_Name2 = $RenamedTo;
11753 }
11754 my $RPos2 = $RelPos{2}{$Member_Name2};
11755 if($RPos2 ne "" and $RPos1 ne $RPos2)
11756 { # different relative positions
11757 my $AbsPos2 = $NameToPosB{$Member_Name2};
11758 if($AbsPos1 ne $AbsPos2)
11759 { # different absolute positions
11760 my $ProblemType = "Moved_Field";
11761 if(not isPublic(\%Type1_Pure, $AbsPos1))
11762 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011763 if($Level eq "Source") {
11764 next;
11765 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011766 $ProblemType = "Moved_Private_Field";
11767 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011768 if($Level eq "Binary"
11769 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011770 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011771 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011772 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011773 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011774 if($MemSize1 ne $MemSize2) {
11775 $ProblemType .= "_And_Size";
11776 }
11777 }
11778 if($ProblemType eq "Moved_Private_Field") {
11779 next;
11780 }
11781 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11782 "Target"=>$Member_Name,
11783 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011784 "Old_Value"=>$RPos1,
11785 "New_Value"=>$RPos2 );
11786 }
11787 }
11788 }
11789 }
11790 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011791 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011792 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11793 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011794 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011795 if(my $RenamedTo = $RenamedField{$Member_Pos})
11796 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011797 if(defined $Constants{2}{$Member_Name})
11798 {
11799 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11800 { # define OLD NEW
11801 next; # Safe
11802 }
11803 }
11804
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011805 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11806 {
11807 if(isPublic(\%Type1_Pure, $Member_Pos))
11808 {
11809 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11810 "Target"=>$Member_Name,
11811 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011812 "Old_Value"=>$Member_Name,
11813 "New_Value"=>$RenamedTo );
11814 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011815 elsif(isReserved($Member_Name))
11816 {
11817 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11818 "Target"=>$Member_Name,
11819 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011820 "Old_Value"=>$Member_Name,
11821 "New_Value"=>$RenamedTo );
11822 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011823 }
11824 elsif($Type1_Pure{"Type"} eq "Enum")
11825 {
11826 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11827 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11828 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011829 "Old_Value"=>$Member_Name,
11830 "New_Value"=>$RenamedTo );
11831 }
11832 }
11833 elsif($RemovedField{$Member_Pos})
11834 { # removed
11835 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11836 {
11837 my $ProblemType = "Removed_Field";
11838 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011839 or isUnnamed($Member_Name))
11840 {
11841 if($Level eq "Source") {
11842 next;
11843 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011844 $ProblemType = "Removed_Private_Field";
11845 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011846 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011847 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011848 {
11849 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11850 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011851 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 +040011852 { # changed offset
11853 $ProblemType .= "_And_Layout";
11854 }
11855 }
11856 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11857 { # affected size
11858 $ProblemType .= "_And_Size";
11859 }
11860 }
11861 if($ProblemType eq "Removed_Private_Field") {
11862 next;
11863 }
11864 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11865 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011866 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011867 }
11868 elsif($Type2_Pure{"Type"} eq "Union")
11869 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011870 if($Level eq "Binary"
11871 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011872 {
11873 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11874 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011875 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011876 }
11877 else
11878 {
11879 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11880 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011881 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011882 }
11883 }
11884 elsif($Type1_Pure{"Type"} eq "Enum")
11885 {
11886 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11887 "Target"=>$Member_Name,
11888 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011889 "Old_Value"=>$Member_Name );
11890 }
11891 }
11892 else
11893 { # changed
11894 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11895 if($Type1_Pure{"Type"} eq "Enum")
11896 {
11897 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11898 next if($Member_Value1 eq "");
11899 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11900 next if($Member_Value2 eq "");
11901 if($Member_Value1 ne $Member_Value2)
11902 {
11903 my $ProblemType = "Enum_Member_Value";
11904 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11905 $ProblemType = "Enum_Last_Member_Value";
11906 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011907 if($SkipConstants{1}{$Member_Name}) {
11908 $ProblemType = "Enum_Private_Member_Value";
11909 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011910 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11911 "Target"=>$Member_Name,
11912 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011913 "Old_Value"=>$Member_Value1,
11914 "New_Value"=>$Member_Value2 );
11915 }
11916 }
11917 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11918 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011919 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11920 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11921
11922 if($Access1 ne "private"
11923 and $Access2 eq "private")
11924 {
11925 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11926 "Target"=>$Member_Name,
11927 "Type_Name"=>$Type1_Pure{"Name"});
11928 }
11929 elsif($Access1 ne "protected"
11930 and $Access1 ne "private"
11931 and $Access2 eq "protected")
11932 {
11933 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11934 "Target"=>$Member_Name,
11935 "Type_Name"=>$Type1_Pure{"Name"});
11936 }
11937
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011938 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11939 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011940 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011941 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
11942 $SizeV1 = $BSize1;
11943 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011944 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011945 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
11946 $SizeV2 = $BSize2;
11947 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011948 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
11949 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011950 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011951 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011952 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011953 {
11954 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
11955 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
11956 { # field size change (including anon-structures and unions)
11957 # - same types
11958 # - unnamed types
11959 # - bitfields
11960 my $ProblemType = "Field_Size";
11961 if(not isPublic(\%Type1_Pure, $Member_Pos)
11962 or isUnnamed($Member_Name))
11963 { # should not be accessed by applications, goes to "Low Severity"
11964 # example: "abidata" members in GStreamer types
11965 $ProblemType = "Private_".$ProblemType;
11966 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011967 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 +040011968 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011969 if($Type2_Pure{"Type"} ne "Union"
11970 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011971 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011972 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 +040011973 { # changed offset
11974 $ProblemType .= "_And_Layout";
11975 }
11976 }
11977 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11978 $ProblemType .= "_And_Type_Size";
11979 }
11980 }
11981 if($ProblemType eq "Private_Field_Size")
11982 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011983 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040011984 if($ProblemType eq "Field_Size")
11985 {
11986 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
11987 { # Low severity
11988 $ProblemType = "Struct_Field_Size_Increased";
11989 }
11990 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011991 if($ProblemType)
11992 { # register a problem
11993 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11994 "Target"=>$Member_Name,
11995 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011996 "Old_Size"=>$SizeV1,
11997 "New_Size"=>$SizeV2);
11998 }
11999 }
12000 }
12001 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12002 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12003 { # do NOT check bitfield type changes
12004 next;
12005 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012006 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012007 {
12008 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12009 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12010 {
12011 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12012 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012013 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012014 }
12015 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12016 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12017 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012018 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012019 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012020 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012021 }
12022 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012023 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12024 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012025 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012026 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12027 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012028
12029 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012030 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012031 or $ProblemType eq "Field_Type_And_Size"
12032 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012033 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012034 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012035 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012036 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012037 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012038 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012039 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012040 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012041 }
12042 }
12043 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12044 {
12045 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012046 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012047 }
12048 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012049 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012050 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012051 }
12052 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12053 {
12054 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012055 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012056 }
12057 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012058 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012059 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012060 }
12061 }
12062 }
12063
12064 if($Level eq "Source")
12065 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012066 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012067 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012068 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12069 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012070
12071 if($ProblemType eq "Field_Type")
12072 {
12073 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012074 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012075 }
12076 }
12077 }
12078 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012079
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012080 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012081 {
12082 my $ProblemType_Init = $ProblemType;
12083 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012084 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012085 if(not isPublic(\%Type1_Pure, $Member_Pos)
12086 or isUnnamed($Member_Name)) {
12087 $ProblemType = "Private_".$ProblemType;
12088 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012089 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 +040012090 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012091 if($Type2_Pure{"Type"} ne "Union"
12092 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012093 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012094 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 +040012095 { # changed offset
12096 $ProblemType .= "_And_Layout";
12097 }
12098 }
12099 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12100 $ProblemType .= "_And_Type_Size";
12101 }
12102 }
12103 }
12104 else
12105 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012106 # TODO: Private_Field_Type rule?
12107
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012108 if(not isPublic(\%Type1_Pure, $Member_Pos)
12109 or isUnnamed($Member_Name)) {
12110 next;
12111 }
12112 }
12113 if($ProblemType eq "Private_Field_Type_And_Size")
12114 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012115 }
12116 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12117 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012118 "Type_Name"=>$Type1_Pure{"Name"});
12119
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012120 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012121 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012122 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012123 }
12124 }
12125 if(not isPublic(\%Type1_Pure, $Member_Pos))
12126 { # do NOT check internal type changes
12127 next;
12128 }
12129 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012130 { # checking member type changes
12131 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12132
12133 my %DupProblems = ();
12134
12135 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012136 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012137 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012138 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012139 if(not defined $AllAffected)
12140 {
12141 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12142 next;
12143 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012144 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012145
12146 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12147 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12148
12149 if(not defined $AllAffected)
12150 {
12151 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012152 }
12153 }
12154 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012155
12156 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012157 }
12158 }
12159 }
12160 }
12161 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12162 { # checking added members, public and private
12163 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12164 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012165 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012166 if($AddedField{$Member_Pos})
12167 { # added
12168 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12169 {
12170 my $ProblemType = "Added_Field";
12171 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012172 or isUnnamed($Member_Name))
12173 {
12174 if($Level eq "Source") {
12175 next;
12176 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012177 $ProblemType = "Added_Private_Field";
12178 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012179 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012180 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012181 {
12182 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12183 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012184 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 +040012185 { # changed offset
12186 $ProblemType .= "_And_Layout";
12187 }
12188 }
12189 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12190 $ProblemType .= "_And_Size";
12191 }
12192 }
12193 if($ProblemType eq "Added_Private_Field")
12194 { # skip added private fields
12195 next;
12196 }
12197 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12198 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012199 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012200 }
12201 elsif($Type2_Pure{"Type"} eq "Union")
12202 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012203 if($Level eq "Binary"
12204 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012205 {
12206 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12207 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012208 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012209 }
12210 else
12211 {
12212 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12213 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012214 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012215 }
12216 }
12217 elsif($Type2_Pure{"Type"} eq "Enum")
12218 {
12219 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12220 next if($Member_Value eq "");
12221 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12222 "Target"=>$Member_Name,
12223 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012224 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012225 }
12226 }
12227 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012228
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012229 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012230 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012231}
12232
12233sub isUnnamed($) {
12234 return $_[0]=~/\Aunnamed\d+\Z/;
12235}
12236
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012237sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012238{
12239 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012240 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12241 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12242 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12243 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012244 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012245 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012246 }
12247 return $TypeName;
12248}
12249
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012250sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012251{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012252 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012253 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012254 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12255 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012256 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012257 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12258 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012259 return () if(not $Type{"Type"});
12260 if($Type{"Type"} ne $Type_Type)
12261 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012262 return () if(not $Type{"BaseType"});
12263 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012264 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012265 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012266 return %Type;
12267}
12268
12269my %TypeSpecAttributes = (
12270 "Const" => 1,
12271 "Volatile" => 1,
12272 "ConstVolatile" => 1,
12273 "Restrict" => 1,
12274 "Typedef" => 1
12275);
12276
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012277sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012278{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012279 my ($TypeId, $Info) = @_;
12280 if(not $TypeId or not $Info
12281 or not $Info->{$TypeId}) {
12282 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012283 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012284 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12285 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12286 }
12287 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012288 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012289 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012290 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012291 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012292 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012293 return %Type;
12294}
12295
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012296sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012297{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012298 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012299 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012300 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12301 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012302 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012303 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12304 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012305 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12306 my $PLevel = 0;
12307 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12308 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012309 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012310 return $PLevel if(not $Type{"BaseType"});
12311 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12312 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12313 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012314}
12315
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012316sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012317{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012318 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012319 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012320 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12321 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012322 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012323 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12324 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012325 return %Type if(not $Type{"BaseType"});
12326 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012327 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012328 return %Type;
12329}
12330
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012331sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012332{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012333 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012334 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012335 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12336 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012337 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012338 my $Qual = "";
12339 if($Type{"Type"} eq "Pointer") {
12340 $Qual .= "*";
12341 }
12342 elsif($Type{"Type"} eq "Ref") {
12343 $Qual .= "&";
12344 }
12345 elsif($Type{"Type"} eq "ConstVolatile") {
12346 $Qual .= "const volatile";
12347 }
12348 elsif($Type{"Type"} eq "Const"
12349 or $Type{"Type"} eq "Volatile"
12350 or $Type{"Type"} eq "Restrict") {
12351 $Qual .= lc($Type{"Type"});
12352 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012353 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012354 return $BQual.$Qual;
12355}
12356
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012357sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012358{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012359 my ($TypeId, $Info) = @_;
12360 if(not $TypeId or not $Info
12361 or not $Info->{$TypeId}) {
12362 return ();
12363 }
12364 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012365 return %Type if(not $Type{"BaseType"});
12366 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012367 {
12368 if($Info->{$BTid}) {
12369 return %{$Info->{$BTid}};
12370 }
12371 else { # something is going wrong
12372 return ();
12373 }
12374 }
12375 else {
12376 return %Type;
12377 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012378}
12379
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012380sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012381{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012382 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012383 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012384 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12385 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012386}
12387
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012388sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012389{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012390 my $Symbol = $_[0];
12391 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12392}
12393
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012394sub isInLineInst($$$) {
12395 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12396}
12397
12398sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012399{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012400 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012401 if($CheckObjectsOnly)
12402 {
12403 if($Symbol!~/\A(_Z|\?)/) {
12404 return 0;
12405 }
12406 if(my $Signature = $tr_name{$Symbol})
12407 {
12408 if(index($Signature,">")==-1) {
12409 return 0;
12410 }
12411 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
12412 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012413 if(index($ShortName,"<")!=-1
12414 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012415 return 1;
12416 }
12417 }
12418 }
12419 }
12420 else
12421 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012422 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012423 {
12424 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
12425 {
12426 if(index($ClassName,"<")!=-1) {
12427 return 1;
12428 }
12429 }
12430 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012431 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012432 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012433 if(index($ShortName,"<")!=-1
12434 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012435 return 1;
12436 }
12437 }
12438 }
12439 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012440}
12441
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012442sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012443{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012444 my ($Symbol, $SInfo, $LibVersion) = @_;
12445 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012446 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012447 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012448 { # class specialization
12449 return 1;
12450 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012451 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012452 { # method specialization
12453 return 1;
12454 }
12455 }
12456 return 0;
12457}
12458
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012459sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012460{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012461 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012462 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012463 { # non-public global data
12464 return 0;
12465 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012466
12467 if(defined $SkipInternal)
12468 {
12469 return 0 if($Symbol=~/($SkipInternal)/);
12470 }
12471
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012472 if($CheckObjectsOnly) {
12473 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
12474 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012475 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012476 { # support for old ABI dumps in --headers-only mode
12477 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12478 {
12479 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12480 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012481 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012482 if(not $PType or $PType eq "Unknown") {
12483 return 0;
12484 }
12485 }
12486 }
12487 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012488 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012489 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012490 if($SkipSymbols{$LibVersion}{$Symbol})
12491 { # user defined symbols to ignore
12492 return 0;
12493 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012494 if($SymbolsListPath and not $SymbolsList{$Symbol})
12495 { # user defined symbols
12496 return 0;
12497 }
12498 if($AppPath and not $SymbolsList_App{$Symbol})
12499 { # user defined symbols (in application)
12500 return 0;
12501 }
12502
12503 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12504
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012505 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12506 if(not $NameSpace and $ClassId)
12507 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012508 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012509 }
12510 if($NameSpace)
12511 { # user defined namespaces to ignore
12512 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12513 return 0;
12514 }
12515 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12516 { # nested namespaces
12517 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12518 return 0;
12519 }
12520 }
12521 }
12522 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
12523 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012524 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012525 { # --skip-headers or <skip_headers> (not <skip_including>)
12526 if($Skip==1) {
12527 return 0;
12528 }
12529 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012530 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012531 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012532 { # user defined types
12533 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12534
12535 if(not $TypesList{$CName})
12536 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012537 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12538 {
12539 $CName=~s/\A\Q$NS\E\:\://g;
12540 }
12541
12542 if(not $TypesList{$CName})
12543 {
12544 my $Found = 0;
12545
12546 while($CName=~s/\:\:.+?\Z//)
12547 {
12548 if($TypesList{$CName})
12549 {
12550 $Found = 1;
12551 last;
12552 }
12553 }
12554
12555 if(not $Found) {
12556 return 0;
12557 }
12558 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012559 }
12560 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012561
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012562 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12563 { # non-target symbols
12564 return 0;
12565 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012566 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012567 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012568 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012569 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012570 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012571 return 0;
12572 }
12573 }
12574 else
12575 {
12576 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012577 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012578 {
12579 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12580 { # inline virtual methods
12581 if($Type=~/InlineVirt/) {
12582 return 1;
12583 }
12584 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12585 if(not $Allocable)
12586 { # check bases
12587 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12588 {
12589 if(not isCopyingClass($DCId, $LibVersion))
12590 { # exists a derived class without default c-tor
12591 $Allocable=1;
12592 last;
12593 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012594 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012595 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012596 if(not $Allocable) {
12597 return 0;
12598 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012599 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012600 else
12601 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012602 return 0;
12603 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012604 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012605 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012606 }
12607 }
12608 return 1;
12609}
12610
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012611sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012612{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012613 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012614 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12615 {
12616 if(link_symbol($Symbol, 1, "+Deps"))
12617 { # linker can find a new symbol
12618 # in the old-version library
12619 # So, it's not a new symbol
12620 next;
12621 }
12622 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012623 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012624 next;
12625 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012626 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012627 }
12628}
12629
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012630sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012631{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012632 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012633 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12634 {
12635 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012636 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012637 }
12638 if(link_symbol($Symbol, 2, "+Deps"))
12639 { # linker can find an old symbol
12640 # in the new-version library
12641 next;
12642 }
12643 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012644 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012645 next;
12646 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012647 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012648 }
12649}
12650
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012651sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012652{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012653 my $Level = $_[0];
12654 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012655 { # checking added symbols
12656 next if($CompleteSignature{2}{$Symbol}{"Private"});
12657 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012658 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012659 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012660 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012661 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012662 { # checking removed symbols
12663 next if($CompleteSignature{1}{$Symbol}{"Private"});
12664 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012665 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012666 { # skip v-tables for templates, that should not be imported by applications
12667 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012668 if(my $CName = $VTableClass{$Symbol})
12669 {
12670 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12671 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012672 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012673 next;
12674 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012675 }
12676 }
12677 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012678 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012679 }
12680 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12681 { # symbols for pure virtual methods cannot be called by clients
12682 next;
12683 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012684 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012685 }
12686}
12687
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012688sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012689{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012690 my ($LibVersion, $V) = @_;
12691 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12692 return $Cache{"checkDump"}{$LibVersion}{$V};
12693 }
12694 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012695}
12696
12697sub detectAdded_H($)
12698{
12699 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012700 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12701 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012702 if($Level eq "Source")
12703 { # remove symbol version
12704 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12705 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012706
12707 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12708 { # skip artificial constructors
12709 next;
12710 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012711 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012712 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12713 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012714 next;
12715 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012716 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012717 next;
12718 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012719 if(not defined $CompleteSignature{1}{$Symbol}
12720 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12721 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012722 if($UsedDump{2}{"SrcBin"})
12723 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012724 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012725 { # support for old and different (!) ABI dumps
12726 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12727 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012728 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012729 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012730 {
12731 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12732 {
12733 if($Lang eq "C")
12734 { # support for old ABI dumps: missed extern "C" functions
12735 next;
12736 }
12737 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012738 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012739 else
12740 {
12741 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012742 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012743 next;
12744 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012745 }
12746 }
12747 }
12748 }
12749 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012750 }
12751 }
12752}
12753
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012754sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012755{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012756 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012757 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12758 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012759 if($Level eq "Source")
12760 { # remove symbol version
12761 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12762 $Symbol=$SN;
12763 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012764 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12765 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012766 next;
12767 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012768 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012769 next;
12770 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012771 if(not defined $CompleteSignature{2}{$Symbol}
12772 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012773 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012774 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012775 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012776 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012777 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012778 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12779 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012780 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012781 if($CheckHeadersOnly)
12782 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012783 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12784 {
12785 if($Lang eq "C")
12786 { # support for old ABI dumps: missed extern "C" functions
12787 next;
12788 }
12789 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012790 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012791 else
12792 {
12793 if(not link_symbol($Symbol, 1, "-Deps"))
12794 { # skip removed inline symbols
12795 next;
12796 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012797 }
12798 }
12799 }
12800 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012801 if(not checkDump(1, "2.15"))
12802 {
12803 if($Symbol=~/_IT_E\Z/)
12804 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12805 next;
12806 }
12807 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012808 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12809 {
12810 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12811 {
12812 if(defined $Constants{2}{$Short})
12813 {
12814 my $Val = $Constants{2}{$Short}{"Value"};
12815 if(defined $Func_ShortName{2}{$Val})
12816 { # old name defined to new
12817 next;
12818 }
12819 }
12820 }
12821
12822 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012823 $RemovedInt{$Level}{$Symbol} = 1;
12824 if($Level eq "Source")
12825 { # search for a source-compatible equivalent
12826 setAlternative($Symbol, $Level);
12827 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012828 }
12829 }
12830}
12831
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012832sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012833{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012834 my $Level = $_[0];
12835 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012836 { # checking added symbols
12837 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012838 next if($CompleteSignature{2}{$Symbol}{"Private"});
12839 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012840 if($Level eq "Binary")
12841 {
12842 if($CompleteSignature{2}{$Symbol}{"InLine"})
12843 {
12844 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12845 { # skip inline non-virtual functions
12846 next;
12847 }
12848 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012849 }
12850 else
12851 { # Source
12852 if($SourceAlternative_B{$Symbol}) {
12853 next;
12854 }
12855 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012856 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012857 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012858 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012859 { # checking removed symbols
12860 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012861 next if($CompleteSignature{1}{$Symbol}{"Private"});
12862 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012863 if($Level eq "Binary")
12864 {
12865 if($CompleteSignature{1}{$Symbol}{"InLine"})
12866 {
12867 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12868 { # skip inline non-virtual functions
12869 next;
12870 }
12871 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012872 }
12873 else
12874 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012875 if(my $Alt = $SourceAlternative{$Symbol})
12876 {
12877 if(defined $CompleteSignature{1}{$Alt}
12878 and $CompleteSignature{1}{$Symbol}{"Const"})
12879 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012880 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012881 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012882 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012883 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012884 }
12885 else
12886 { # do NOT show removed symbol
12887 next;
12888 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012889 }
12890 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012891 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012892 }
12893}
12894
12895sub addParamNames($)
12896{
12897 my $LibraryVersion = $_[0];
12898 return if(not keys(%AddIntParams));
12899 my $SecondVersion = $LibraryVersion==1?2:1;
12900 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
12901 {
12902 next if(not keys(%{$AddIntParams{$Interface}}));
12903 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012904 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012905 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
12906 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012907 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012908 if(defined $CompleteSignature{$SecondVersion}{$Interface}
12909 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
12910 {
12911 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
12912 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12913 }
12914 }
12915 else {
12916 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12917 }
12918 }
12919 }
12920 }
12921}
12922
12923sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012924{ # detect changed typedefs to show
12925 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012926 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
12927 {
12928 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012929 my $BName1 = $Typedef_BaseName{1}{$Typedef};
12930 if(not $BName1 or isAnon($BName1)) {
12931 next;
12932 }
12933 my $BName2 = $Typedef_BaseName{2}{$Typedef};
12934 if(not $BName2 or isAnon($BName2)) {
12935 next;
12936 }
12937 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012938 $ChangedTypedef{$Typedef} = 1;
12939 }
12940 }
12941}
12942
12943sub get_symbol_suffix($$)
12944{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012945 my ($Symbol, $Full) = @_;
12946 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040012947 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012948 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012949 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012950 if(not $Full) {
12951 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
12952 }
12953 return $Suffix;
12954}
12955
12956sub get_symbol_prefix($$)
12957{
12958 my ($Symbol, $LibVersion) = @_;
12959 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
12960 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12961 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012962 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012963 }
12964 return $ShortName;
12965}
12966
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012967sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012968{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012969 my $Symbol = $_[0];
12970 my $PSymbol = $Symbol;
12971 if(not defined $CompleteSignature{2}{$PSymbol}
12972 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
12973 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
12974 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012975 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012976 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012977 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012978 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012979 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
12980 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012981 {
12982 if(defined $CompleteSignature{2}{$PSymbol}
12983 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12984 {
12985 $SourceAlternative{$Symbol} = $PSymbol;
12986 $SourceAlternative_B{$PSymbol} = $Symbol;
12987 if(not defined $CompleteSignature{1}{$PSymbol}
12988 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12989 $SourceReplacement{$Symbol} = $PSymbol;
12990 }
12991 }
12992 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012993 }
12994 else
12995 {
12996 foreach my $Sp ("KV", "VK", "K", "V")
12997 {
12998 if($PSymbol=~s/\A_ZN$Sp/_ZN/
12999 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13000 {
13001 if(defined $CompleteSignature{2}{$PSymbol}
13002 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13003 {
13004 $SourceAlternative{$Symbol} = $PSymbol;
13005 $SourceAlternative_B{$PSymbol} = $Symbol;
13006 if(not defined $CompleteSignature{1}{$PSymbol}
13007 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13008 $SourceReplacement{$Symbol} = $PSymbol;
13009 }
13010 }
13011 }
13012 $PSymbol = $Symbol;
13013 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013014 }
13015 }
13016 }
13017 return "";
13018}
13019
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013020sub getSymKind($$)
13021{
13022 my ($Symbol, $LibVersion) = @_;
13023 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13024 {
13025 return "Global_Data";
13026 }
13027 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13028 {
13029 return "Method";
13030 }
13031 return "Function";
13032}
13033
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013034sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013035{
13036 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013037 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013038
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013039 mergeBases($Level);
13040
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013041 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013042 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013043 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013044 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013045 next;
13046 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013047 if(defined $CompleteSignature{1}{$Symbol}
13048 and $CompleteSignature{1}{$Symbol}{"Header"})
13049 { # double-check added symbol
13050 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013051 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013052 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013053 next;
13054 }
13055 if($Symbol=~/\A(_Z|\?)/)
13056 { # C++
13057 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13058 }
13059 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13060 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013061 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13062 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013063 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013064 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013065 {
13066 if($TName_Tid{1}{$AffectedClass_Name})
13067 { # class should exist in previous version
13068 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13069 { # old v-table is NOT copied by old applications
13070 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13071 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013072 "Target"=>get_Signature($Symbol, 2),
13073 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013074 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013075 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013076 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013077 }
13078 }
13079 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013080 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13081 { # check all removed exported symbols
13082 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013083 next;
13084 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013085 if(defined $CompleteSignature{2}{$Symbol}
13086 and $CompleteSignature{2}{$Symbol}{"Header"})
13087 { # double-check removed symbol
13088 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013089 }
13090 if($CompleteSignature{1}{$Symbol}{"Private"})
13091 { # skip private methods
13092 next;
13093 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013094 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013095 next;
13096 }
13097 $CheckedSymbols{$Level}{$Symbol} = 1;
13098 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13099 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013100 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13101 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013102 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013103 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13104 {
13105 if($TName_Tid{2}{$AffectedClass_Name})
13106 { # class should exist in newer version
13107 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13108 { # old v-table is NOT copied by old applications
13109 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13110 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013111 "Target"=>get_Signature($OverriddenMethod, 1),
13112 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013113 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013114 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013115 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013116 }
13117 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013118 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013119 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013120 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013121 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013122 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013123 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013124 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013125 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013126 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013127 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013128 {
13129 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13130 "Target"=>$tr_name{$Symbol},
13131 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013132 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013133 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013134 else
13135 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013136 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013137 "Target"=>$tr_name{$Symbol},
13138 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013139 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013140 }
13141 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013142 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013143 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013144 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013145 {
13146 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13147 "Target"=>$tr_name{$Symbol},
13148 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013149 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013150 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013151 else
13152 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013153 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013154 "Target"=>$tr_name{$Symbol},
13155 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013156 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013157 }
13158 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013159 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13160 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13161 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13162 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13163 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013164 {
13165 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013166 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013167 $ProblemType = "Global_Data_Symbol_Changed_Type";
13168 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013169 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13170 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013171 "Old_Type"=>$RTName1,
13172 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013173 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013174 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013175 }
13176 }
13177 }
13178 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013179 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013180 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013181 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013182 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013183 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013184 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013185 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013186 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13187 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013188 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013189 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013190 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013191 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013192 }
13193 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013194 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13195 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013196 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013197 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013198 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013199 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013200 }
13201 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013202 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013203 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013204 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013205 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013206 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013207 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013208 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013209 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013210 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013211 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013212 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013213 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013214 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013215 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013216 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013217 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013218 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013219 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013220 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013221 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013222 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013223 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013224 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013225 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013226 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013227 { # "volatile" to non-"volatile"
13228
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013229 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013230 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013231 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013232 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013233 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013234 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013235 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013236 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013237 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013238 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013239 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013240 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013241 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013242 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013243 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013244 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013245 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013246 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13247 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013248 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013249 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013250 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013251 }
13252 }
13253 }
13254 }
13255 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013256 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13257 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013258 $CurrentSymbol = $Symbol;
13259
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013260 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13261 if($Level eq "Source")
13262 { # remove symbol version
13263 $Symbol=$SN;
13264 }
13265 else
13266 { # Binary
13267 if(not $SV)
13268 { # symbol without version
13269 if(my $VSym = $SymVer{1}{$Symbol})
13270 { # the symbol is linked with versioned symbol
13271 if($CompleteSignature{2}{$VSym}{"MnglName"})
13272 { # show report for symbol@ver only
13273 next;
13274 }
13275 elsif(not link_symbol($VSym, 2, "-Deps"))
13276 { # changed version: sym@v1 to sym@v2
13277 # do NOT show report for symbol
13278 next;
13279 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013280 }
13281 }
13282 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013283 my $PSymbol = $Symbol;
13284 if($Level eq "Source"
13285 and my $S = $SourceReplacement{$Symbol})
13286 { # take a source-compatible replacement function
13287 $PSymbol = $S;
13288 }
13289 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013290 { # private symbols
13291 next;
13292 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013293 if(not defined $CompleteSignature{1}{$Symbol}
13294 or not defined $CompleteSignature{2}{$PSymbol})
13295 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013296 next;
13297 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013298 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13299 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13300 { # no mangled name
13301 next;
13302 }
13303 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13304 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013305 { # without a header
13306 next;
13307 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013308
13309 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13310 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13311 { # became pure
13312 next;
13313 }
13314 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13315 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13316 { # became non-pure
13317 next;
13318 }
13319
13320 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13321 { # exported, target, inline virtual and pure virtual
13322 next;
13323 }
13324 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13325 { # exported, target, inline virtual and pure virtual
13326 next;
13327 }
13328
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013329 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013330 {
13331 if($CompleteSignature{1}{$Symbol}{"Data"}
13332 and $CompleteSignature{2}{$PSymbol}{"Data"})
13333 {
13334 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13335 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13336 if(defined $Value1)
13337 {
13338 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13339 if(defined $Value2)
13340 {
13341 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13342 if($Value1 ne $Value2)
13343 {
13344 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13345 "Old_Value"=>$Value1,
13346 "New_Value"=>$Value2,
13347 "Target"=>get_Signature($Symbol, 1) );
13348 }
13349 }
13350 }
13351 }
13352 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013353
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013354 if($CompleteSignature{2}{$PSymbol}{"Private"})
13355 {
13356 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13357 "Target"=>get_Signature_M($PSymbol, 2) );
13358 }
13359 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13360 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13361 {
13362 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13363 "Target"=>get_Signature_M($PSymbol, 2) );
13364 }
13365 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13366 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13367 {
13368 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13369 "Target"=>get_Signature_M($PSymbol, 2) );
13370 }
13371
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013372 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013373 mergeVirtualTables($Symbol, $Level);
13374
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013375 if($COMPILE_ERRORS)
13376 { # if some errors occurred at the compiling stage
13377 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013378 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013379 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013380 { # missed information about parameters in newer version
13381 next;
13382 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013383 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013384 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013385 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013386 next;
13387 }
13388 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013389 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013390 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013391 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013392 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13393 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013394 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13395 "Target"=>get_Signature($Symbol, 1)
13396 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013397 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013398 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013399 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13400 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013401 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013402 "Target"=>get_Signature($Symbol, 1)
13403 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013404 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013405 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13406 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013407 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013408 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013409 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013410 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13411 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13412 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013413 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013414 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013415 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13416 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013417 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013418 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013419 my $ProblemType = "Virtual_Method_Position";
13420 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13421 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013422 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013423 if(isUsedClass($Class_Id, 1, $Level))
13424 {
13425 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013426 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013427 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013428 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13429 next;
13430 }
13431 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013432 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013433 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13434 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013435 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013436 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013437 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013438 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013439 }
13440 }
13441 }
13442 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013443 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13444 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013445 { # do NOT check type changes in pure virtuals
13446 next;
13447 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013448 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013449 if($Symbol=~/\A(_Z|\?)/
13450 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013451 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013452 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013453 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013454 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013455 }
13456 }
13457 else
13458 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013459 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013460 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013461 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013462 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13463 last if($PType2_Name eq "...");
13464 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13465 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013466 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013467 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013468 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013469 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13470 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013471 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13472 $ParamPos_Prev = "lost";
13473 }
13474 }
13475 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013476 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013477 }
13478 if($ParamPos_Prev eq "lost")
13479 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013480 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013481 {
13482 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013483 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013484 $ProblemType = "Added_Unnamed_Parameter";
13485 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013486 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013487 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013488 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013489 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013490 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013491 }
13492 else
13493 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013494 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013495 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013496 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013497 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13498 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013499 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013500 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013501 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013502 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013503 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013504 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013505 "Param_Type"=>$PType2_Name,
13506 "Old_Value"=>$PName_Old,
13507 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013508 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013509 }
13510 }
13511 else
13512 {
13513 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013514 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013515 $ProblemType = "Added_Middle_Unnamed_Parameter";
13516 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013517 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013518 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013519 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013520 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013521 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013522 }
13523 }
13524 }
13525 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013526 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013527 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013528 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013529 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013530 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013531 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013532 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013533 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013534 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013535 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13536 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013537 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013538 }
13539 }
13540 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013541 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013542 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013543 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013544 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13545 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013546 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13547 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013548 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013549 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013550 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013551 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13552 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013553 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13554 $ParamPos_New = "lost";
13555 }
13556 }
13557 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013558 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013559 }
13560 if($ParamPos_New eq "lost")
13561 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013562 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013563 {
13564 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013565 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013566 $ProblemType = "Removed_Unnamed_Parameter";
13567 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013568 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013569 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013570 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013571 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013572 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013573 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013574 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013575 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013576 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013577 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013578 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013579 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013580 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013581 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013582 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013583 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013584 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013585 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013586 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013587 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013588 "Old_Value"=>$PName,
13589 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013590 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013591 }
13592 }
13593 else
13594 {
13595 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013596 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013597 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13598 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013599 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013600 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013601 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013602 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013603 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013604 }
13605 }
13606 }
13607 }
13608 }
13609 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013610 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13611 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013612 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013613
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013614 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013615 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013616 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13617 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013618 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013619
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013620 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013621 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013622 if($SubProblemType eq "Return_Type_And_Size") {
13623 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13624 }
13625 elsif($SubProblemType eq "Return_Type_Format") {
13626 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13627 }
13628 else {
13629 $ProblemTypes{"Global_Data_Type"} = 1;
13630 }
13631
13632 # quals
13633 if($SubProblemType eq "Return_Type"
13634 or $SubProblemType eq "Return_Type_And_Size"
13635 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013636 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013637 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13638 { # const to non-const
13639 if($RR==2) {
13640 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13641 }
13642 else {
13643 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13644 }
13645 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013646 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013647 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13648 { # non-const to const
13649 if($RA==2) {
13650 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13651 }
13652 else {
13653 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13654 }
13655 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013656 }
13657 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013658 }
13659 else
13660 {
13661 # quals
13662 if($SubProblemType eq "Return_Type"
13663 or $SubProblemType eq "Return_Type_And_Size"
13664 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013665 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013666 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013667 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013668 if(addedQual($Old_Value, $New_Value, "volatile"))
13669 {
13670 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13671 if($Level ne "Source"
13672 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13673 $ProblemTypes{"Return_Type"} = 1;
13674 }
13675 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013676 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013677 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13678 {
13679 if($RA==2) {
13680 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13681 }
13682 else {
13683 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13684 }
13685 if($Level ne "Source"
13686 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13687 $ProblemTypes{"Return_Type"} = 1;
13688 }
13689 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013690 }
13691 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013692 if($Level eq "Binary"
13693 and not $CompleteSignature{1}{$Symbol}{"Data"})
13694 {
13695 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13696 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13697 { # if one of the architectures is unknown
13698 # then set other arhitecture to unknown too
13699 ($Arch1, $Arch2) = ("unknown", "unknown");
13700 }
13701 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013702 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013703 {
13704 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13705 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13706 }
13707 else
13708 {
13709 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13710 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13711 }
13712
13713 if($SubProblemType eq "Return_Type_Became_Void")
13714 {
13715 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13716 { # parameters stack has been affected
13717 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013718 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013719 }
13720 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013721 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013722 }
13723 }
13724 }
13725 elsif($SubProblemType eq "Return_Type_From_Void")
13726 {
13727 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13728 { # parameters stack has been affected
13729 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013730 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013731 }
13732 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013733 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013734 }
13735 }
13736 }
13737 elsif($SubProblemType eq "Return_Type"
13738 or $SubProblemType eq "Return_Type_And_Size"
13739 or $SubProblemType eq "Return_Type_Format")
13740 {
13741 if($Conv1{"Method"} ne $Conv2{"Method"})
13742 {
13743 if($Conv1{"Method"} eq "stack")
13744 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013745 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013746 }
13747 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013748 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013749 }
13750 }
13751 else
13752 {
13753 if($Conv1{"Method"} eq "reg")
13754 {
13755 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13756 {
13757 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013758 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013759 }
13760 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013761 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013762 }
13763 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013764 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013765 }
13766 }
13767 }
13768 }
13769 }
13770 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013771
13772 if(not keys(%ProblemTypes))
13773 { # default
13774 $ProblemTypes{$SubProblemType} = 1;
13775 }
13776
13777 foreach my $ProblemType (keys(%ProblemTypes))
13778 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013779 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013780 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013781 }
13782 if($ReturnType1_Id and $ReturnType2_Id)
13783 {
13784 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013785 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13786
13787 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013788
13789 if($CompleteSignature{1}{$Symbol}{"Data"})
13790 {
13791 if($Level eq "Binary")
13792 {
13793 if(get_PLevel($ReturnType1_Id, 1)==0)
13794 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013795 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013796 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013797
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013798 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13799 {
13800 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013801 {
13802 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13803 {
13804 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13805 last;
13806 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013807 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013808 }
13809 }
13810 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013811 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013812 {
13813 if(defined $GlobalDataObject{1}{$Symbol}
13814 and defined $GlobalDataObject{2}{$Symbol})
13815 {
13816 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13817 my $New_Size = $GlobalDataObject{2}{$Symbol};
13818 if($Old_Size!=$New_Size)
13819 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013820 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013821 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013822 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013823 }
13824 }
13825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013826 }
13827 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013828
13829 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013830 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013831 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013832 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013833 my $NewLocation = "retval";
13834 if($SubLocation and $SubLocation ne "retval") {
13835 $NewLocation = "retval->".$SubLocation;
13836 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013837 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13838 }
13839 }
13840
13841 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13842 {
13843 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13844 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013845 my $NewLocation = "retval";
13846 if($SubLocation and $SubLocation ne "retval") {
13847 $NewLocation = "retval->".$SubLocation;
13848 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013849 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013850 }
13851 }
13852 }
13853
13854 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013855 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13856 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13857 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013858 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013859 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013860 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13861 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013862 if($ThisPtr1_Id and $ThisPtr2_Id)
13863 {
13864 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013865 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13866 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013867 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013868 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013869 {
13870 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013871 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013872 }
13873 }
13874 }
13875 }
13876 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013877 if($Level eq "Binary") {
13878 mergeVTables($Level);
13879 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013880 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13881 $CheckedSymbols{$Level}{$Symbol} = 1;
13882 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013883}
13884
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013885sub rmQuals($$)
13886{
13887 my ($Value, $Qual) = @_;
13888 if(not $Qual) {
13889 return $Value;
13890 }
13891 if($Qual eq "all")
13892 { # all quals
13893 $Qual = "const|volatile|restrict";
13894 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013895 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013896 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013897 }
13898 return $Value;
13899}
13900
13901sub cmpBTypes($$$$)
13902{
13903 my ($T1, $T2, $V1, $V2) = @_;
13904 $T1 = uncover_typedefs($T1, $V1);
13905 $T2 = uncover_typedefs($T2, $V2);
13906 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
13907}
13908
13909sub addedQual($$$)
13910{
13911 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013912 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013913}
13914
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013915sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013916{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013917 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013918 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013919}
13920
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013921sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013922{
13923 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
13924 $Old_Value = uncover_typedefs($Old_Value, $V1);
13925 $New_Value = uncover_typedefs($New_Value, $V2);
13926 if($Old_Value eq $New_Value)
13927 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013928 return 0;
13929 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013930 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013931 { # without a qual
13932 return 0;
13933 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013934 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013935 { # became non-qual
13936 return 1;
13937 }
13938 else
13939 {
13940 my @BQ1 = getQualModel($Old_Value, $Qual);
13941 my @BQ2 = getQualModel($New_Value, $Qual);
13942 foreach (0 .. $#BQ1)
13943 { # removed qual
13944 if($BQ1[$_]==1
13945 and $BQ2[$_]!=1)
13946 {
13947 return 2;
13948 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013949 }
13950 }
13951 return 0;
13952}
13953
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013954sub getQualModel($$)
13955{
13956 my ($Value, $Qual) = @_;
13957 if(not $Qual) {
13958 return $Value;
13959 }
13960
13961 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013962 while($Value=~/(\w+)/ and $1 ne $Qual) {
13963 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013964 }
13965 $Value=~s/[^\*\&\w]+//g;
13966
13967 # modeling
13968 # int*const*const == 011
13969 # int**const == 001
13970 my @Model = ();
13971 my @Elems = split(/[\*\&]/, $Value);
13972 if(not @Elems) {
13973 return (0);
13974 }
13975 foreach (@Elems)
13976 {
13977 if($_ eq $Qual) {
13978 push(@Model, 1);
13979 }
13980 else {
13981 push(@Model, 0);
13982 }
13983 }
13984
13985 return @Model;
13986}
13987
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013988my %StringTypes = map {$_=>1} (
13989 "char*",
13990 "char const*"
13991);
13992
13993my %CharTypes = map {$_=>1} (
13994 "char",
13995 "char const"
13996);
13997
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013998sub showVal($$$)
13999{
14000 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014001 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014002 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014003 if(substr($Value, 0, 2) eq "_Z")
14004 {
14005 if(my $Unmangled = $tr_name{$Value}) {
14006 return $Unmangled;
14007 }
14008 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014009 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014010 { # strings
14011 return "\"$Value\"";
14012 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014013 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014014 { # characters
14015 return "\'$Value\'";
14016 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014017 if($Value eq "")
14018 { # other
14019 return "\'\'";
14020 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014021 return $Value;
14022}
14023
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014024sub getRegs($$$)
14025{
14026 my ($LibVersion, $Symbol, $Pos) = @_;
14027
14028 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14029 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014030 my %Regs = ();
14031 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14032 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014033 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014034 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14035 }
14036 }
14037
14038 return join(", ", sort keys(%Regs));
14039 }
14040
14041 return undef;
14042}
14043
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014044sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014045{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014046 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014047 if(not $Symbol) {
14048 return;
14049 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014050 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14051 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14052 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14053 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014054 if(not $PType1_Id
14055 or not $PType2_Id) {
14056 return;
14057 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014058
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014059 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014060 { # do not merge "this"
14061 if($PName1 eq "this" or $PName2 eq "this") {
14062 return;
14063 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014064 }
14065
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014066 my %Type1 = get_Type($PType1_Id, 1);
14067 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014068
14069 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14070
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014071 my %BaseType1 = get_BaseType($PType1_Id, 1);
14072 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014073
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014074 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014075
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014076 if($Level eq "Binary")
14077 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014078 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014079 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14080 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14081 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14082 {
14083 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014084 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014085 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014086 }
14087 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14088 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14089 {
14090 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014091 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014092 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014094 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014095
14096 if(defined $UsedDump{1}{"DWARF"}
14097 and defined $UsedDump{2}{"DWARF"})
14098 {
14099 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14100 {
14101 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14102 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14103 if($Old_Regs and $New_Regs)
14104 {
14105 if($Old_Regs ne $New_Regs)
14106 {
14107 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14108 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014109 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014110 "Old_Value"=>$Old_Regs,
14111 "New_Value"=>$New_Regs );
14112 }
14113 }
14114 elsif($Old_Regs and not $New_Regs)
14115 {
14116 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14117 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014118 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014119 "Old_Value"=>$Old_Regs );
14120 }
14121 elsif(not $Old_Regs and $New_Regs)
14122 {
14123 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14124 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014125 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014126 "New_Value"=>$New_Regs );
14127 }
14128 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14129 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14130 {
14131 if($Old_Offset ne $New_Offset)
14132 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014133 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14134 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14135
14136 $Old_Offset = $Old_Offset - $Start1;
14137 $New_Offset = $New_Offset - $Start2;
14138
14139 if($Old_Offset ne $New_Offset)
14140 {
14141 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14142 "Target"=>$PName1,
14143 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14144 "Old_Value"=>$Old_Offset,
14145 "New_Value"=>$New_Offset );
14146 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014147 }
14148 }
14149 }
14150 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014151 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014152 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14153 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014154 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014155 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014156 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14157 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014158 if(not checkDump(1, "2.13")
14159 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014160 { # support for old ABI dumps
14161 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014162 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014163 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014164 and $Value_Old eq "false" and $Value_New eq "0")
14165 { # int class::method ( bool p = 0 );
14166 # old ABI dumps: "false"
14167 # new ABI dumps: "0"
14168 $Value_Old = "0";
14169 }
14170 }
14171 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014172 if(not checkDump(1, "2.18")
14173 and checkDump(2, "2.18"))
14174 { # support for old ABI dumps
14175 if(not defined $Value_Old
14176 and substr($Value_New, 0, 2) eq "_Z") {
14177 $Value_Old = $Value_New;
14178 }
14179 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014180 if(defined $Value_Old)
14181 {
14182 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14183 if(defined $Value_New)
14184 {
14185 $Value_New = showVal($Value_New, $PType2_Id, 2);
14186 if($Value_Old ne $Value_New)
14187 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014188 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014189 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014190 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014191 "Old_Value"=>$Value_Old,
14192 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014193 }
14194 }
14195 else
14196 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014197 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014198 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014199 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014200 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014201 }
14202 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014203 elsif(defined $Value_New)
14204 {
14205 $Value_New = showVal($Value_New, $PType2_Id, 2);
14206 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14207 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014208 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014209 "New_Value"=>$Value_New );
14210 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014211 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014212
14213 if($ChkRnmd)
14214 {
14215 if($PName1 and $PName2 and $PName1 ne $PName2
14216 and $PType1_Id!=-1 and $PType2_Id!=-1
14217 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14218 { # except unnamed "..." value list (Id=-1)
14219 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14220 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014221 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014222 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14223 "Old_Value"=>$PName1,
14224 "New_Value"=>$PName2,
14225 "New_Signature"=>get_Signature($Symbol, 2) );
14226 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014227 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014228
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014229 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014230 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014231
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014232 foreach my $SubProblemType (keys(%SubProblems))
14233 { # add new problems, remove false alarms
14234 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14235 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014236
14237 # quals
14238 if($SubProblemType eq "Parameter_Type"
14239 or $SubProblemType eq "Parameter_Type_And_Size"
14240 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014241 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014242 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014243 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014244 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014245 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014246 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014247 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14248 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14249 }
14250 }
14251 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14252 {
14253 if(removedQual($Old_Value, $New_Value, "volatile")) {
14254 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014255 }
14256 }
14257 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14258 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14259 { # int to "int const"
14260 delete($SubProblems{$SubProblemType});
14261 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014262 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014263 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14264 { # "int const" to int
14265 delete($SubProblems{$SubProblemType});
14266 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014267 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14268 { # "const" to non-"const"
14269 if($RR==2) {
14270 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14271 }
14272 else {
14273 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14274 }
14275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014276 }
14277 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014278
14279 if($Level eq "Source")
14280 {
14281 foreach my $SubProblemType (keys(%SubProblems))
14282 {
14283 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14284 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14285
14286 if($SubProblemType eq "Parameter_Type")
14287 {
14288 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14289 delete($SubProblems{$SubProblemType});
14290 }
14291 }
14292 }
14293 }
14294
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014295 foreach my $SubProblemType (keys(%SubProblems))
14296 { # modify/register problems
14297 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14298 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014299 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14300 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014301
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014302 my $NewProblemType = $SubProblemType;
14303 if($Old_Value eq "..." and $New_Value ne "...")
14304 { # change from "..." to "int"
14305 if($ParamPos1==0)
14306 { # ISO C requires a named argument before "..."
14307 next;
14308 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014309 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014310 }
14311 elsif($New_Value eq "..." and $Old_Value ne "...")
14312 { # change from "int" to "..."
14313 if($ParamPos2==0)
14314 { # ISO C requires a named argument before "..."
14315 next;
14316 }
14317 $NewProblemType = "Parameter_Became_VaList";
14318 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014319 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014320 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014321 {
14322 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014323 if($Arch1 eq "unknown"
14324 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014325 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014326 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014327 ($Arch1, $Arch2) = ("unknown", "unknown");
14328 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014329 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014330 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014331 { # real
14332 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14333 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14334 }
14335 else
14336 { # model
14337 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14338 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14339 }
14340 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014341 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014342 if($Conv1{"Method"} eq "stack")
14343 {
14344 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14345 $NewProblemType = "Parameter_Type_And_Stack";
14346 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014347 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014348 elsif($Conv1{"Method"} eq "reg")
14349 {
14350 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14351 $NewProblemType = "Parameter_Type_And_Register";
14352 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014353 }
14354 }
14355 else
14356 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014357 if($Conv1{"Method"} eq "stack") {
14358 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014359 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014360 elsif($Conv1{"Method"} eq "register") {
14361 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014362 }
14363 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014364 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14365 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014366 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014367 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014368 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014369 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014370 "New_Signature"=>get_Signature($Symbol, 2) );
14371 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014372 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014373
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014374 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014375
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014376 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014377 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14378 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014379 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014380 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014381 {
14382 my $NewProblemType = $SubProblemType;
14383 if($SubProblemType eq "DataType_Size")
14384 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014385 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014386 { # stack has been affected
14387 $NewProblemType = "DataType_Size_And_Stack";
14388 }
14389 }
14390 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014391 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014392 }
14393 }
14394}
14395
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014396sub find_ParamPair_Pos_byName($$$)
14397{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014398 my ($Name, $Symbol, $LibVersion) = @_;
14399 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014400 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014401 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14402 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014403 {
14404 return $ParamPos;
14405 }
14406 }
14407 return "lost";
14408}
14409
14410sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14411{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014412 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014413 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014414 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014415 {
14416 next if($Order eq "backward" and $ParamPos>$MediumPos);
14417 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014418 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14419 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014420 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014421 push(@Positions, $ParamPos);
14422 }
14423 }
14424 return @Positions;
14425}
14426
14427sub getTypeIdByName($$)
14428{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014429 my ($TypeName, $LibVersion) = @_;
14430 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014431}
14432
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014433sub diffTypes($$$)
14434{
14435 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14436 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14437 }
14438 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14439 { # skip recursive declarations
14440 return 0;
14441 }
14442
14443 pushType($_[0], $_[1], \@RecurTypes_Diff);
14444 my $Diff = diffTypes_I(@_);
14445 pop(@RecurTypes_Diff);
14446
14447 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14448}
14449
14450sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014451{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014452 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014453
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014454 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14455 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014456
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014457 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14458 { # equal types
14459 return 0;
14460 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014461 if($Type1_Pure{"Name"} eq "void")
14462 { # from void* to something
14463 return 0;
14464 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014465 if($Type1_Pure{"Name"}=~/\*/
14466 or $Type2_Pure{"Name"}=~/\*/)
14467 { # compared in detectTypeChange()
14468 return 0;
14469 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014470
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014471 my %FloatType = map {$_=>1} (
14472 "float",
14473 "double",
14474 "long double"
14475 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014476
14477 my $T1 = $Type1_Pure{"Type"};
14478 my $T2 = $Type2_Pure{"Type"};
14479
14480 if($T1 eq "Struct"
14481 and $T2 eq "Class")
14482 { # compare as data structures
14483 $T2 = "Struct";
14484 }
14485
14486 if($T1 eq "Class"
14487 and $T2 eq "Struct")
14488 { # compare as data structures
14489 $T1 = "Struct";
14490 }
14491
14492 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014493 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014494 if($T1 eq "Intrinsic"
14495 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014496 { # "int" to "enum"
14497 return 0;
14498 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014499 elsif($T2 eq "Intrinsic"
14500 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014501 { # "enum" to "int"
14502 return 0;
14503 }
14504 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014505 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014506 # ...
14507 return 1;
14508 }
14509 }
14510 else
14511 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014512 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014513 {
14514 if($FloatType{$Type1_Pure{"Name"}}
14515 or $FloatType{$Type2_Pure{"Name"}})
14516 { # "float" to "double"
14517 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014518 if($Level eq "Source")
14519 { # Safe
14520 return 0;
14521 }
14522 else {
14523 return 1;
14524 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014525 }
14526 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014527 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014528 {
14529 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14530 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014531 if(not @Membs1
14532 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014533 { # private
14534 return 0;
14535 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014536 if($#Membs1!=$#Membs2)
14537 { # different number of elements
14538 return 1;
14539 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014540 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014541 {
14542 foreach my $Pos (@Membs1)
14543 { # compare elements by name and value
14544 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14545 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14546 { # different names
14547 return 1;
14548 }
14549 }
14550 }
14551 else
14552 {
14553 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014554 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014555 if($Level eq "Source")
14556 {
14557 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14558 { # different names
14559 return 1;
14560 }
14561 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014562
14563 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14564 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14565
14566 if($MT1{"Name"} ne $MT2{"Name"}
14567 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14568 {
14569 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14570 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14571
14572 if($PL1 ne $PL2)
14573 { # different pointer level
14574 return 1;
14575 }
14576
14577 # compare base types
14578 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14579 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14580
14581 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14582 { # different types
14583 return 1;
14584 }
14585 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014586 }
14587 }
14588 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014589 else
14590 {
14591 # TODO: arrays, etc.
14592 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014593 }
14594 return 0;
14595}
14596
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014597sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014598{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014599 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014600 if(not $Type1_Id or not $Type2_Id) {
14601 return ();
14602 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014603 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014604 my %Type1 = get_Type($Type1_Id, 1);
14605 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014606 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14607 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14608 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14609 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 +040014610
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014611 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14612 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014613 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14614 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14615 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14616 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14617 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14618 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14619 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014620 if($Type1{"Name"} eq $Type2{"Name"})
14621 {
14622 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14623 { # will be reported in mergeTypes() as typedef problem
14624 return ();
14625 }
14626 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14627 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14628 if(%Typedef_1 and %Typedef_2)
14629 {
14630 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14631 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14632 { # const Typedef
14633 return ();
14634 }
14635 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014636 }
14637 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14638 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014639 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014640 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14641 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014642 {
14643 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14644 "Old_Value"=>$Type1_Base{"Name"},
14645 "New_Value"=>$Type2_Base{"Name"},
14646 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014647 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014648 }
14649 else
14650 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014651 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014652 { # format change
14653 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14654 "Old_Value"=>$Type1_Base{"Name"},
14655 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014656 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014657 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014658 }
14659 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14660 {
14661 %{$LocalProblems{$Prefix."_BaseType"}}=(
14662 "Old_Value"=>$Type1_Base{"Name"},
14663 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014664 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014665 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014666 }
14667 }
14668 }
14669 }
14670 elsif($Type1{"Name"} ne $Type2{"Name"})
14671 { # type change
14672 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14673 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014674 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014675 and $Type1_Pure{"Name"} eq "void")
14676 {
14677 %{$LocalProblems{"Return_Type_From_Void"}}=(
14678 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014679 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014680 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014681 elsif($Prefix eq "Return"
14682 and $Type2_Pure{"Name"} eq "void")
14683 {
14684 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14685 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014686 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014687 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014688 else
14689 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014690 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014691 and $Type1{"Size"} and $Type2{"Size"}
14692 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014693 {
14694 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14695 "Old_Value"=>$Type1{"Name"},
14696 "New_Value"=>$Type2{"Name"},
14697 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014698 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014699 }
14700 else
14701 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014702 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014703 { # format change
14704 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14705 "Old_Value"=>$Type1{"Name"},
14706 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014707 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014708 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014709 }
14710 elsif(tNameLock($Type1_Id, $Type2_Id))
14711 { # FIXME: correct this condition
14712 %{$LocalProblems{$Prefix."_Type"}}=(
14713 "Old_Value"=>$Type1{"Name"},
14714 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014715 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014716 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014717 }
14718 }
14719 }
14720 }
14721 }
14722 if($Type1_PLevel!=$Type2_PLevel)
14723 {
14724 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14725 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14726 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014727 if($Level eq "Source")
14728 {
14729 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014730 "Old_Value"=>$Type1_PLevel,
14731 "New_Value"=>$Type2_PLevel);
14732 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014733 else
14734 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014735 if($Type2_PLevel>$Type1_PLevel)
14736 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014737 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14738 "Old_Value"=>$Type1_PLevel,
14739 "New_Value"=>$Type2_PLevel);
14740 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014741 else
14742 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014743 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14744 "Old_Value"=>$Type1_PLevel,
14745 "New_Value"=>$Type2_PLevel);
14746 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014747 }
14748 }
14749 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014750 if($Type1_Pure{"Type"} eq "Array"
14751 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014752 { # base_type[N] -> base_type[N]
14753 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014754 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014755 foreach my $SubProblemType (keys(%SubProblems))
14756 {
14757 $SubProblemType=~s/_Type/_BaseType/g;
14758 next if(defined $LocalProblems{$SubProblemType});
14759 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14760 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14761 }
14762 }
14763 }
14764 return %LocalProblems;
14765}
14766
14767sub tNameLock($$)
14768{
14769 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014770 my $Changed = 0;
14771 if(differentDumps("G"))
14772 { # different GCC versions
14773 $Changed = 1;
14774 }
14775 elsif(differentDumps("V"))
14776 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014777 if(not checkDump(1, "2.20")
14778 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014779 { # latest names update
14780 # 2.6: added restrict qualifier
14781 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014782 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014783 $Changed = 1;
14784 }
14785 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014786
14787 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14788 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14789
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014790 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14791 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14792
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014793 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014794 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014795 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014796 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014797 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014798 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014799 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014800 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014801 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014802 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014803 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14804 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14805 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014806 { # equal base types
14807 return 0;
14808 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014809
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014810 if(not checkDump(1, "2.13")
14811 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014812 { # broken array names in ABI dumps < 2.13
14813 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014814 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014815 return 0;
14816 }
14817 }
14818
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014819 if(not checkDump(1, "2.6")
14820 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014821 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014822 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014823 and $TN2=~/\brestrict\b/) {
14824 return 0;
14825 }
14826 }
14827
14828 if(not checkDump(1, "2.20")
14829 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014830 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014831 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14832 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014833 return 0;
14834 }
14835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014836 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014837 else
14838 {
14839 # typedef struct {...} type_t
14840 # typedef struct type_t {...} type_t
14841 if(index($TN1, " ".$TN2)!=-1)
14842 {
14843 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14844 return 0;
14845 }
14846 }
14847 if(index($TN2, " ".$TN1)!=-1)
14848 {
14849 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14850 return 0;
14851 }
14852 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014853
14854 if($TT1 eq "FuncPtr"
14855 and $TT2 eq "FuncPtr")
14856 {
14857 my $TN1_C = $TN1;
14858 my $TN2_C = $TN2;
14859
14860 $TN1_C=~s/\b(struct|union) //g;
14861 $TN2_C=~s/\b(struct|union) //g;
14862
14863 if($TN1_C eq $TN2_C) {
14864 return 0;
14865 }
14866 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014867 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014868
14869 my ($N1, $N2) = ($TN1, $TN2);
14870 $N1=~s/\b(struct|union) //g;
14871 $N2=~s/\b(struct|union) //g;
14872
14873 if($N1 eq $N2)
14874 { # QList<struct QUrl> and QList<QUrl>
14875 return 0;
14876 }
14877
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014878 return 1;
14879}
14880
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014881sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014882{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014883 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014884 if(defined $Cache{"differentDumps"}{$Check}) {
14885 return $Cache{"differentDumps"}{$Check};
14886 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014887 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014888 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014889 if($Check eq "G")
14890 {
14891 if(getGccVersion(1) ne getGccVersion(2))
14892 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014893 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014894 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014895 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014896 if($Check eq "V")
14897 {
14898 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14899 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14900 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014901 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014902 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014903 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014904 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014905 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014906}
14907
14908sub formatVersion($$)
14909{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014910 my ($V, $Digits) = @_;
14911 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014912 return join(".", splice(@Elems, 0, $Digits));
14913}
14914
14915sub htmlSpecChars($)
14916{
14917 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014918 if(not $Str) {
14919 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014920 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014921 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14922 $Str=~s/</&lt;/g;
14923 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
14924 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014925 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
14926 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014927 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014928 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014929 $Str=~s/\n/<br\/>/g;
14930 $Str=~s/\"/&quot;/g;
14931 $Str=~s/\'/&#39;/g;
14932 return $Str;
14933}
14934
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014935sub xmlSpecChars($)
14936{
14937 my $Str = $_[0];
14938 if(not $Str) {
14939 return $Str;
14940 }
14941
14942 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14943 $Str=~s/</&lt;/g;
14944 $Str=~s/>/&gt;/g;
14945
14946 $Str=~s/\"/&quot;/g;
14947 $Str=~s/\'/&#39;/g;
14948
14949 return $Str;
14950}
14951
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014952sub xmlSpecChars_R($)
14953{
14954 my $Str = $_[0];
14955 if(not $Str) {
14956 return $Str;
14957 }
14958
14959 $Str=~s/&amp;/&/g;
14960 $Str=~s/&lt;/</g;
14961 $Str=~s/&gt;/>/g;
14962
14963 $Str=~s/&quot;/"/g;
14964 $Str=~s/&#39;/'/g;
14965
14966 return $Str;
14967}
14968
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014969sub black_name($)
14970{
14971 my $Name = $_[0];
14972 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
14973}
14974
14975sub highLight_Signature($)
14976{
14977 my $Signature = $_[0];
14978 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
14979}
14980
14981sub highLight_Signature_Italic_Color($)
14982{
14983 my $Signature = $_[0];
14984 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
14985}
14986
14987sub separate_symbol($)
14988{
14989 my $Symbol = $_[0];
14990 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
14991 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
14992 ($Name, $Spec, $Ver) = ($1, $2, $3);
14993 }
14994 return ($Name, $Spec, $Ver);
14995}
14996
14997sub cut_f_attrs($)
14998{
14999 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15000 return $2;
15001 }
15002 return "";
15003}
15004
15005sub highLight_Signature_PPos_Italic($$$$$)
15006{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015007 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15008 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015009 if($CheckObjectsOnly) {
15010 $ItalicParams=$ColorParams=0;
15011 }
15012 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15013 my $Return = "";
15014 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15015 $Return = $2;
15016 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015017 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015018 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015019 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015020 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015021 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015022 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015023 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015024 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015025 }
15026 return $Signature;
15027 }
15028 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15029 $Begin.=" " if($Begin!~/ \Z/);
15030 $End = cut_f_attrs($Signature);
15031 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015032 my ($Short, $Params) = split_Signature($Signature);
15033 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015034 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015035 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015036 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015037 $Part=~s/\A\s+|\s+\Z//g;
15038 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15039 if($Part=~/\([\*]+(\w+)\)/i) {
15040 $ParamName = $1;#func-ptr
15041 }
15042 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15043 $ParamName = $1;
15044 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015045 if(not $ParamName)
15046 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015047 push(@Parts, $Part_Styled);
15048 next;
15049 }
15050 if($ItalicParams and not $TName_Tid{1}{$Part}
15051 and not $TName_Tid{2}{$Part})
15052 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015053 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015054 if($Param_Pos ne ""
15055 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015056 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015057 }
15058 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015059 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015060 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015061 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015062 }
15063 $Part_Styled=~s/,(\w)/, $1/g;
15064 push(@Parts, $Part_Styled);
15065 }
15066 if(@Parts)
15067 {
15068 foreach my $Num (0 .. $#Parts)
15069 {
15070 if($Num==$#Parts)
15071 { # add ")" to the last parameter
15072 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15073 }
15074 elsif(length($Parts[$Num])<=45) {
15075 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15076 }
15077 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015078 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015079 }
15080 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015081 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015082 }
15083 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015084 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015085 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015086 $Signature=~s!\[\]![&#160;]!g;
15087 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015088 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15089 if($SymbolVersion) {
15090 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15091 }
15092 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015093}
15094
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015095sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015096{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015097 my $Signature = $_[0];
15098 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15099 {
15100 $Signature=~s/\A\Q$ShortName\E\(//g;
15101 cut_f_attrs($Signature);
15102 $Signature=~s/\)\Z//;
15103 return ($ShortName, $Signature);
15104 }
15105
15106 # error
15107 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015108}
15109
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015110sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015111{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015112 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015113 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015114 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15115 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015116 foreach my $Pos (0 .. length($Params) - 1)
15117 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015118 my $S = substr($Params, $Pos, 1);
15119 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015120 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015121 }
15122 if($S eq "," and
15123 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015124 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015125 if($Comma)
15126 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015127 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015128 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015129 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015130 }
15131 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015132 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015133 }
15134 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015135 if(not $Sp)
15136 { # remove spaces
15137 foreach (@Parts)
15138 {
15139 s/\A //g;
15140 s/ \Z//g;
15141 }
15142 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015143 return @Parts;
15144}
15145
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015146sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015147{
15148 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015149 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015150 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015151 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15152 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015153 $Center+=length($1);
15154 }
15155 foreach my $Pos (0 .. length($Sign)-1)
15156 {
15157 my $S = substr($Sign, $Pos, 1);
15158 if($S eq $Target)
15159 {
15160 if($B{"("}==$B{")"}
15161 and $B{"<"}==$B{">"}) {
15162 return $Center;
15163 }
15164 }
15165 if(defined $B{$S}) {
15166 $B{$S}+=1;
15167 }
15168 $Center+=1;
15169 }
15170 return 0;
15171}
15172
15173sub appendFile($$)
15174{
15175 my ($Path, $Content) = @_;
15176 return if(not $Path);
15177 if(my $Dir = get_dirname($Path)) {
15178 mkpath($Dir);
15179 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015180 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015181 print FILE $Content;
15182 close(FILE);
15183}
15184
15185sub writeFile($$)
15186{
15187 my ($Path, $Content) = @_;
15188 return if(not $Path);
15189 if(my $Dir = get_dirname($Path)) {
15190 mkpath($Dir);
15191 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015192 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015193 print FILE $Content;
15194 close(FILE);
15195}
15196
15197sub readFile($)
15198{
15199 my $Path = $_[0];
15200 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015201 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015202 local $/ = undef;
15203 my $Content = <FILE>;
15204 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015205 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015206 $Content=~s/\r/\n/g;
15207 }
15208 return $Content;
15209}
15210
15211sub get_filename($)
15212{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015213 if(defined $Cache{"get_filename"}{$_[0]}) {
15214 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015215 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015216 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15217 return ($Cache{"get_filename"}{$_[0]}=$1);
15218 }
15219 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015220}
15221
15222sub get_dirname($)
15223{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015224 if(defined $Cache{"get_dirname"}{$_[0]}) {
15225 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015226 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015227 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15228 return ($Cache{"get_dirname"}{$_[0]}=$1);
15229 }
15230 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015231}
15232
15233sub separate_path($) {
15234 return (get_dirname($_[0]), get_filename($_[0]));
15235}
15236
15237sub esc($)
15238{
15239 my $Str = $_[0];
15240 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15241 return $Str;
15242}
15243
15244sub readLineNum($$)
15245{
15246 my ($Path, $Num) = @_;
15247 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015248 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015249 foreach (1 ... $Num) {
15250 <FILE>;
15251 }
15252 my $Line = <FILE>;
15253 close(FILE);
15254 return $Line;
15255}
15256
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015257sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015258{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015259 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015260 return () if(not $Path or not -f $Path);
15261 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015262 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15263 {
15264 foreach my $AttrVal (split(/;/, $1))
15265 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015266 if($AttrVal=~/(.+):(.+)/)
15267 {
15268 my ($Name, $Value) = ($1, $2);
15269 $Attributes{$Name} = $Value;
15270 }
15271 }
15272 }
15273 return \%Attributes;
15274}
15275
15276sub is_abs($) {
15277 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15278}
15279
15280sub get_abs_path($)
15281{ # abs_path() should NOT be called for absolute inputs
15282 # because it can change them
15283 my $Path = $_[0];
15284 if(not is_abs($Path)) {
15285 $Path = abs_path($Path);
15286 }
15287 return $Path;
15288}
15289
15290sub get_OSgroup()
15291{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015292 my $N = $Config{"osname"};
15293 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015294 return "macos";
15295 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015296 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015297 return "bsd";
15298 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015299 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015300 return "beos";
15301 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015302 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015303 return "symbian";
15304 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015305 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015306 return "windows";
15307 }
15308 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015309 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015310 }
15311}
15312
15313sub getGccVersion($)
15314{
15315 my $LibVersion = $_[0];
15316 if($GCC_VERSION{$LibVersion})
15317 { # dump version
15318 return $GCC_VERSION{$LibVersion};
15319 }
15320 elsif($UsedDump{$LibVersion}{"V"})
15321 { # old-version dumps
15322 return "unknown";
15323 }
15324 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15325 if(not $GccVersion) {
15326 return "unknown";
15327 }
15328 return $GccVersion;
15329}
15330
15331sub showArch($)
15332{
15333 my $Arch = $_[0];
15334 if($Arch eq "arm"
15335 or $Arch eq "mips") {
15336 return uc($Arch);
15337 }
15338 return $Arch;
15339}
15340
15341sub getArch($)
15342{
15343 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015344
15345 if($TargetArch) {
15346 return $TargetArch;
15347 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015348 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015349 { # dump version
15350 return $CPU_ARCH{$LibVersion};
15351 }
15352 elsif($UsedDump{$LibVersion}{"V"})
15353 { # old-version dumps
15354 return "unknown";
15355 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015356
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015357 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015358}
15359
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015360sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015361{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015362 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015363
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015364 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015365 if(getArch(1) ne getArch(2)
15366 or getArch(1) eq "unknown"
15367 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015368 { # don't show architecture in the header
15369 $ArchInfo="";
15370 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015371 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015372 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015373 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015374 }
15375 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015376 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015377 }
15378 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015379 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015380 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015381
15382 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15383 {
15384 my $M1 = $UsedDump{1}{"M"};
15385 my $M2 = $UsedDump{2}{"M"};
15386
15387 if($M1 eq $M2)
15388 {
15389 $Title .= " report for the <span style='color:Blue;'>$M1</span> object";
15390 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15391 }
15392 else
15393 {
15394 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$Descriptor{1}{"Version"}."</span>)";
15395 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$Descriptor{2}{"Version"}."</span>) objects";
15396 }
15397 }
15398 else
15399 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015400 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015401 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15402 }
15403
15404 $Title .= $ArchInfo;
15405
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015406 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015407 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015408 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015409 $Title = "<h1>".$Title."</h1>\n";
15410 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015411}
15412
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015413sub get_CheckedHeaders($)
15414{
15415 my $LibVersion = $_[0];
15416
15417 my @Headers = ();
15418
15419 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15420 {
15421 my $File = get_filename($Path);
15422 if(not is_target_header($File, $LibVersion)) {
15423 next;
15424 }
15425
15426 if(skipHeader($File, $LibVersion)) {
15427 next;
15428 }
15429
15430 push(@Headers, $Path);
15431 }
15432
15433 return @Headers;
15434}
15435
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015436sub get_SourceInfo()
15437{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015438 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015439 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015440 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015441 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015442 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015443 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15444 $CheckedHeaders .= "<div class='h_list'>\n";
15445 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15446 {
15447 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15448 my $Name = get_filename($Identity);
15449 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15450 $CheckedHeaders .= $Name.$Comment."<br/>\n";
15451 }
15452 $CheckedHeaders .= "</div>\n";
15453 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015454 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015455
15456 if(my @Sources = keys(%{$Registered_Sources{1}}))
15457 {
15458 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15459 $CheckedSources .= "<div class='h_list'>\n";
15460 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15461 {
15462 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15463 my $Name = get_filename($Identity);
15464 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15465 $CheckedSources .= $Name.$Comment."<br/>\n";
15466 }
15467 $CheckedSources .= "</div>\n";
15468 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15469 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015470 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015471 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015472 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015473 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015474 $CheckedLibs .= "<div class='lib_list'>\n";
15475 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15476 {
15477 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15478 $CheckedLibs .= $Library."<br/>\n";
15479 }
15480 $CheckedLibs .= "</div>\n";
15481 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015482 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015483 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15484}
15485
15486sub get_ObjTitle()
15487{
15488 if(defined $UsedDump{1}{"DWARF"}) {
15489 return "Objects";
15490 }
15491 else {
15492 return ucfirst($SLIB_TYPE)." Libraries";
15493 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015494}
15495
15496sub get_TypeProblems_Count($$$)
15497{
15498 my ($TypeChanges, $TargetPriority, $Level) = @_;
15499 my $Type_Problems_Count = 0;
15500 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15501 {
15502 my %Kinds_Target = ();
15503 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15504 {
15505 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15506 {
15507 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015508 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15509 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015510 if($Kinds_Target{$Kind}{$Target}) {
15511 next;
15512 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015513
15514 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15515 {
15516 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15517 { # select a problem with the highest priority
15518 next;
15519 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015520 }
15521 $Kinds_Target{$Kind}{$Target} = 1;
15522 $Type_Problems_Count += 1;
15523 }
15524 }
15525 }
15526 return $Type_Problems_Count;
15527}
15528
15529sub get_Summary($)
15530{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015531 my $Level = $_[0];
15532 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015533 $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 +040015534 %{$RESULT{$Level}} = (
15535 "Problems"=>0,
15536 "Warnings"=>0,
15537 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015538 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015539 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015540 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015541 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015542 {
15543 if(not defined $CompatRules{$Level}{$Kind})
15544 { # unknown rule
15545 if(not $UnknownRules{$Level}{$Kind})
15546 { # only one warning
15547 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15548 $UnknownRules{$Level}{$Kind}=1;
15549 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015550 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015551 }
15552 }
15553 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015554 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15555 {
15556 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15557 {
15558 if(not defined $CompatRules{$Level}{$Kind})
15559 { # unknown rule
15560 if(not $UnknownRules{$Level}{$Kind})
15561 { # only one warning
15562 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15563 $UnknownRules{$Level}{$Kind}=1;
15564 }
15565 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15566 }
15567 }
15568 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015569 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015570 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015571 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015572 {
15573 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15574 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015575 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015576 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015577 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015578 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015579 $Added += 1;
15580 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015581 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015582 {
15583 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015584 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015585 }
15586 else
15587 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015588 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015589 $I_Other += 1;
15590 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015591 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015592 $I_Problems_High += 1;
15593 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015594 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015595 $I_Problems_Medium += 1;
15596 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015597 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015598 $I_Problems_Low += 1;
15599 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015600 if(($Severity ne "Low" or $StrictCompat)
15601 and $Severity ne "Safe") {
15602 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015603 }
15604 }
15605 }
15606 }
15607 }
15608 }
15609 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015610 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015611 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015612 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015613 {
15614 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15615 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015616 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015617 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015618 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15619 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015620 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015621 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15622
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015623 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015624 { # select a problem with the highest priority
15625 next;
15626 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015627
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015628 if(($Severity ne "Low" or $StrictCompat)
15629 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015630 {
15631 if(defined $TotalAffected{$Level}{$Interface})
15632 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015633 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15634 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015635 }
15636 }
15637 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015638 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015639 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015640 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015641
15642 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15643
15644 if($MaxSeverity)
15645 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015646 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15647 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015648 }
15649 }
15650 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015651 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015652 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015653 }
15654 }
15655 }
15656 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015657
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015658 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15659 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15660 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15661 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015662
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015663 %TypeChanges = (); # free memory
15664
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015665 if($CheckObjectsOnly)
15666 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015667 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015668 }
15669 else
15670 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015671 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015672 if($ExtendedCheck)
15673 { # don't count external_func_0 for constants
15674 $SCount-=1;
15675 }
15676 if($SCount)
15677 {
15678 my %Weight = (
15679 "High" => 100,
15680 "Medium" => 50,
15681 "Low" => 25
15682 );
15683 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015684 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015685 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015686 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015687 }
15688 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015689 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015690 }
15691 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015692 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15693 if($RESULT{$Level}{"Affected"}>=100) {
15694 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015695 }
15696
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015697 $RESULT{$Level}{"Problems"} += $Removed;
15698 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015699 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015700 if($StrictCompat) {
15701 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15702 }
15703 else {
15704 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15705 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015706
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015707 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015708 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015709 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015710 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015711 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015712 if($Severity eq "Safe")
15713 {
15714 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015715 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015716 elsif($Severity eq "Low")
15717 {
15718 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015719 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015720 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015721 }
15722
15723 if($C_Problems_Low)
15724 {
15725 if($StrictCompat) {
15726 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15727 }
15728 else {
15729 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015730 }
15731 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015732 if($RESULT{$Level}{"Problems"}
15733 and $RESULT{$Level}{"Affected"}) {
15734 $RESULT{$Level}{"Verdict"} = "incompatible";
15735 }
15736 else {
15737 $RESULT{$Level}{"Verdict"} = "compatible";
15738 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015739
15740 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15741 if(not $TotalTypes)
15742 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015743 $TotalTypes = keys(%{$TName_Tid{1}});
15744 }
15745
15746 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15747 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15748
15749 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15750
15751 if($ReportFormat eq "xml")
15752 { # XML
15753 # test info
15754 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15755 $TestInfo .= " <version1>\n";
15756 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015757 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015758 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15759 $TestInfo .= " </version1>\n";
15760
15761 $TestInfo .= " <version2>\n";
15762 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015763 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015764 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15765 $TestInfo .= " </version2>\n";
15766 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15767
15768 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015769 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015770 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015771 $TestResults .= " <headers>\n";
15772 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15773 {
15774 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15775 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15776 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15777 }
15778 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015779 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015780
15781 if(my @Sources = keys(%{$Registered_Sources{1}}))
15782 {
15783 $TestResults .= " <sources>\n";
15784 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15785 {
15786 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15787 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15788 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15789 }
15790 $TestResults .= " </sources>\n";
15791 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015792
15793 $TestResults .= " <libs>\n";
15794 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15795 {
15796 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15797 $TestResults .= " <name>$Library</name>\n";
15798 }
15799 $TestResults .= " </libs>\n";
15800
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015801 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015802 $TestResults .= " <types>".$TotalTypes."</types>\n";
15803
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015804 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15805 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015806 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15807
15808 # problem summary
15809 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15810 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15811
15812 $Problem_Summary .= " <problems_with_types>\n";
15813 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15814 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15815 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15816 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15817 $Problem_Summary .= " </problems_with_types>\n";
15818
15819 $Problem_Summary .= " <problems_with_symbols>\n";
15820 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15821 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15822 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015823 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015824 $Problem_Summary .= " </problems_with_symbols>\n";
15825
15826 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015827 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015828 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015829
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015830 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15831
15832 return ($TestInfo.$TestResults.$Problem_Summary, "");
15833 }
15834 else
15835 { # HTML
15836 # test info
15837 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015838 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015839 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetTitle</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015840
15841 my (@VInf1, @VInf2, $AddTestInfo) = ();
15842 if($Arch1 ne "unknown"
15843 and $Arch2 ne "unknown")
15844 { # CPU arch
15845 if($Arch1 eq $Arch2)
15846 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015847 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015848 }
15849 else
15850 { # go to the version number
15851 push(@VInf1, showArch($Arch1));
15852 push(@VInf2, showArch($Arch2));
15853 }
15854 }
15855 if($GccV1 ne "unknown"
15856 and $GccV2 ne "unknown"
15857 and $OStarget ne "windows")
15858 { # GCC version
15859 if($GccV1 eq $GccV2)
15860 { # go to the separate section
15861 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15862 }
15863 else
15864 { # go to the version number
15865 push(@VInf1, "gcc ".$GccV1);
15866 push(@VInf2, "gcc ".$GccV2);
15867 }
15868 }
15869 # show long version names with GCC version and CPU architecture name (if different)
15870 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15871 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15872 $TestInfo .= $AddTestInfo;
15873 #if($COMMON_LANGUAGE{1}) {
15874 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15875 #}
15876 if($ExtendedCheck) {
15877 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15878 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015879 if($JoinReport)
15880 {
15881 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015882 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015883 }
15884 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015885 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015886 }
15887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015888 $TestInfo .= "</table>\n";
15889
15890 # test results
15891 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015892 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015893
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030015894 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015895 {
15896 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15897 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15898 }
15899 elsif($CheckObjectsOnly) {
15900 $TestResults .= "<tr><th>Total Header Files</th><td>0&#160;(not&#160;analyzed)</td></tr>\n";
15901 }
15902
15903 if(my @Sources = keys(%{$Registered_Sources{1}}))
15904 {
15905 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15906 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15907 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015908
15909 if(not $ExtendedCheck)
15910 {
15911 my $Libs_Link = "0";
15912 $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 +040015913 $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 +040015914 }
15915
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015916 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015917
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015918 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015919 if($JoinReport) {
15920 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15921 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015922 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015923 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015924 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15925 }
15926 else {
15927 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15928 }
15929 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015930 $TestResults .= "</table>\n";
15931
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015932 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015933 # problem summary
15934 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015935 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015936 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15937
15938 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015939 if($Added>0)
15940 {
15941 if($JoinReport) {
15942 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15943 }
15944 else {
15945 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15946 }
15947 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015948 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015949 $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 +040015950
15951 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015952 if($Removed>0)
15953 {
15954 if($JoinReport) {
15955 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15956 }
15957 else {
15958 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
15959 }
15960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015961 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015962 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
15963 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015964
15965 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015966 $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 +040015967 $TH_Link = "n/a" if($CheckObjectsOnly);
15968 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015969 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
15970 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015971
15972 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015973 $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 +040015974 $TM_Link = "n/a" if($CheckObjectsOnly);
15975 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015976 $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 +040015977
15978 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015979 $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 +040015980 $TL_Link = "n/a" if($CheckObjectsOnly);
15981 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015982 $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 +040015983
15984 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015985 $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 +040015986 $IH_Link = "n/a" if($CheckObjectsOnly);
15987 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015988 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
15989 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015990
15991 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015992 $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 +040015993 $IM_Link = "n/a" if($CheckObjectsOnly);
15994 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015995 $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 +040015996
15997 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015998 $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 +040015999 $IL_Link = "n/a" if($CheckObjectsOnly);
16000 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016001 $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 +040016002
16003 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016004 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16005 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016006 }
16007 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016008 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016009 $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 +040016010
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016011 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016012 if($T_Other and not $CheckObjectsOnly)
16013 {
16014 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016015 $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 +040016016 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016017
16018 if($I_Other and not $CheckObjectsOnly)
16019 {
16020 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016021 $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 +040016022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016023
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016024 if($C_Other and not $CheckObjectsOnly)
16025 {
16026 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16027 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
16028 }
16029
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016030 $META_DATA .= "tool_version:$TOOL_VERSION";
16031 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016032 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016033 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16034 }
16035}
16036
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016037sub getStyle($$$)
16038{
16039 my ($Subj, $Act, $Num) = @_;
16040 my %Style = (
16041 "A"=>"new",
16042 "R"=>"failed",
16043 "S"=>"passed",
16044 "L"=>"warning",
16045 "M"=>"failed",
16046 "H"=>"failed"
16047 );
16048 if($Num>0) {
16049 return " class='".$Style{$Act}."'";
16050 }
16051 return "";
16052}
16053
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016054sub show_number($)
16055{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016056 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016057 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016058 my $Num = cut_off_number($_[0], 2, 0);
16059 if($Num eq "0")
16060 {
16061 foreach my $P (3 .. 7)
16062 {
16063 $Num = cut_off_number($_[0], $P, 1);
16064 if($Num ne "0") {
16065 last;
16066 }
16067 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016068 }
16069 if($Num eq "0") {
16070 $Num = $_[0];
16071 }
16072 return $Num;
16073 }
16074 return $_[0];
16075}
16076
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016077sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016078{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016079 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016080 if($num!~/\./)
16081 {
16082 $num .= ".";
16083 foreach (1 .. $digs_to_cut-1) {
16084 $num .= "0";
16085 }
16086 }
16087 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16088 {
16089 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16090 $num .= "0";
16091 }
16092 }
16093 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16094 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16095 }
16096 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016097 if($z) {
16098 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16099 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016100 return $num;
16101}
16102
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016103sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016104{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016105 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016106 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016107
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016108 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016109 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16110 {
16111 my $Header = $Constants{1}{$Constant}{"Header"};
16112 if(not $Header)
16113 { # added
16114 $Header = $Constants{2}{$Constant}{"Header"}
16115 }
16116
16117 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16118 {
16119 if(not defined $CompatRules{$Level}{$Kind}) {
16120 next;
16121 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016122 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016123 next;
16124 }
16125 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16126 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016127 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016128
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016129 if($ReportFormat eq "xml")
16130 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016131 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016132 {
16133 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016134 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016135 {
16136 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016137 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16138 {
16139 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16140 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16141 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016142
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016143 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16144 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16145 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016146 if($Overcome) {
16147 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16148 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016149 $CHANGED_CONSTANTS .= " </problem>\n";
16150 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016151 $CHANGED_CONSTANTS .= " </constant>\n";
16152 }
16153 $CHANGED_CONSTANTS .= " </header>\n";
16154 }
16155 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16156 }
16157 else
16158 { # HTML
16159 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016160 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016161 {
16162 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016163 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016164 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016165 my $Report = "";
16166
16167 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16168 {
16169 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16170 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16171 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16172 $Number += 1;
16173 }
16174 if($Report)
16175 {
16176 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16177 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16178 $Report = insertIDs($Report);
16179 }
16180 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016181 }
16182 $CHANGED_CONSTANTS .= "<br/>\n";
16183 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016184 if($CHANGED_CONSTANTS)
16185 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016186 my $Title = "Problems with Constants, $TargetSeverity Severity";
16187 if($TargetSeverity eq "Safe")
16188 { # Safe Changes
16189 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016190 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016191 $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 +040016192 }
16193 }
16194 return $CHANGED_CONSTANTS;
16195}
16196
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016197sub getTitle($$$)
16198{
16199 my ($Header, $Library, $NameSpace) = @_;
16200 my $Title = "";
16201 if($Library and $Library!~/\.\w+\Z/) {
16202 $Library .= " (.$LIB_EXT)";
16203 }
16204 if($Header and $Library)
16205 {
16206 $Title .= "<span class='h_name'>$Header</span>";
16207 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16208 }
16209 elsif($Library) {
16210 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16211 }
16212 elsif($Header) {
16213 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16214 }
16215 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016216 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016217 }
16218 return $Title;
16219}
16220
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016221sub get_Report_Added($)
16222{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016223 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016224 my $ADDED_INTERFACES = "";
16225 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016226 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016227 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016228 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016229 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016230 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016231 {
16232 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16233 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016234 if($Level eq "Source" and $ReportFormat eq "html")
16235 { # do not show library name in HTML report
16236 $DyLib = "";
16237 }
16238 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016239 }
16240 }
16241 }
16242 if($ReportFormat eq "xml")
16243 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016244 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016245 {
16246 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016247 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016248 {
16249 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016250 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016251 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16252 }
16253 $ADDED_INTERFACES .= " </library>\n";
16254 }
16255 $ADDED_INTERFACES .= " </header>\n";
16256 }
16257 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16258 }
16259 else
16260 { # HTML
16261 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016262 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016263 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016264 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016265 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016266 my %NameSpaceSymbols = ();
16267 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016268 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016269 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016270 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016271 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016272 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16273 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016274 foreach my $Interface (@SortedInterfaces)
16275 {
16276 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016277 my $Signature = get_Signature($Interface, 2);
16278 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016279 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016280 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016281 if($Interface=~/\A(_Z|\?)/)
16282 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016283 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016284 $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 +040016285 }
16286 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016287 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016288 }
16289 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016290 else
16291 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016292 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016293 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016294 }
16295 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016296 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016297 }
16298 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016299 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016300 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016302 }
16303 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016304 if($ADDED_INTERFACES)
16305 {
16306 my $Anchor = "<a name='Added'></a>";
16307 if($JoinReport) {
16308 $Anchor = "<a name='".$Level."_Added'></a>";
16309 }
16310 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016311 }
16312 }
16313 return $ADDED_INTERFACES;
16314}
16315
16316sub get_Report_Removed($)
16317{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016318 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016319 my $REMOVED_INTERFACES = "";
16320 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016321 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016322 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016323 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016324 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016325 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016326 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016327 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16328 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016329 if($Level eq "Source" and $ReportFormat eq "html")
16330 { # do not show library name in HTML report
16331 $DyLib = "";
16332 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016333 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016334 }
16335 }
16336 }
16337 if($ReportFormat eq "xml")
16338 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016339 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016340 {
16341 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016342 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016343 {
16344 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016345 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16346 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016347 }
16348 $REMOVED_INTERFACES .= " </library>\n";
16349 }
16350 $REMOVED_INTERFACES .= " </header>\n";
16351 }
16352 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16353 }
16354 else
16355 { # HTML
16356 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016357 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016358 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016359 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016360 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016361 my %NameSpaceSymbols = ();
16362 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016363 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016364 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016365 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016366 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016367 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16368 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016369 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016370 {
16371 $Removed_Number += 1;
16372 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016373 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016374 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016375 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016376 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016377 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016378 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016379 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016380 $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 +040016381 }
16382 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016383 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016384 }
16385 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016386 else
16387 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016388 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016389 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016390 }
16391 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016392 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016393 }
16394 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016395 }
16396 }
16397 $REMOVED_INTERFACES .= "<br/>\n";
16398 }
16399 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016400 if($REMOVED_INTERFACES)
16401 {
16402 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16403 if($JoinReport) {
16404 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16405 }
16406 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016407 }
16408 }
16409 return $REMOVED_INTERFACES;
16410}
16411
16412sub getXmlParams($$)
16413{
16414 my ($Content, $Problem) = @_;
16415 return "" if(not $Content or not $Problem);
16416 my %XMLparams = ();
16417 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16418 {
16419 my $Macro = "\@".lc($Attr);
16420 if($Content=~/\Q$Macro\E/) {
16421 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16422 }
16423 }
16424 my @PString = ();
16425 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016426 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016427 }
16428 if(@PString) {
16429 return " ".join(" ", @PString);
16430 }
16431 else {
16432 return "";
16433 }
16434}
16435
16436sub addMarkup($)
16437{
16438 my $Content = $_[0];
16439 # auto-markup
16440 $Content=~s/\n[ ]*//; # spaces
16441 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16442 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016443 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016444 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16445 if($Content=~/\ANOTE:/)
16446 { # notes
16447 $Content=~s!(NOTE):!<b>$1</b>:!g;
16448 }
16449 else {
16450 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16451 }
16452 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16453 my @Keywords = (
16454 "void",
16455 "const",
16456 "static",
16457 "restrict",
16458 "volatile",
16459 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016460 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016461 );
16462 my $MKeys = join("|", @Keywords);
16463 foreach (@Keywords) {
16464 $MKeys .= "|non-".$_;
16465 }
16466 $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 +040016467
16468 # Markdown
16469 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16470 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016471 return $Content;
16472}
16473
16474sub applyMacroses($$$$)
16475{
16476 my ($Level, $Kind, $Content, $Problem) = @_;
16477 return "" if(not $Content or not $Problem);
16478 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16479 $Content = addMarkup($Content);
16480 # macros
16481 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16482 {
16483 my $Macro = "\@".lc($Attr);
16484 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016485 if(not defined $Value
16486 or $Value eq "") {
16487 next;
16488 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016489 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016490 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016491 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
16492 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016493 $Value = black_name($Value);
16494 }
16495 elsif($Value=~/\s/) {
16496 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16497 }
16498 elsif($Value=~/\A\d+\Z/
16499 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16500 { # bits to bytes
16501 if($Value % $BYTE_SIZE)
16502 { # bits
16503 if($Value==1) {
16504 $Value = "<b>".$Value."</b> bit";
16505 }
16506 else {
16507 $Value = "<b>".$Value."</b> bits";
16508 }
16509 }
16510 else
16511 { # bytes
16512 $Value /= $BYTE_SIZE;
16513 if($Value==1) {
16514 $Value = "<b>".$Value."</b> byte";
16515 }
16516 else {
16517 $Value = "<b>".$Value."</b> bytes";
16518 }
16519 }
16520 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016521 else
16522 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016523 $Value = "<b>".htmlSpecChars($Value)."</b>";
16524 }
16525 $Content=~s/\Q$Macro\E/$Value/g;
16526 }
16527
16528 if($Content=~/(\A|[^\@\w])\@\w/)
16529 {
16530 if(not $IncompleteRules{$Level}{$Kind})
16531 { # only one warning
16532 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16533 $IncompleteRules{$Level}{$Kind} = 1;
16534 }
16535 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016536 return $Content;
16537}
16538
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016539sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016540{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016541 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016542 my $INTERFACE_PROBLEMS = "";
16543 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016544
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016545 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016546 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016547 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16548 if($SV and defined $CompatProblems{$Level}{$SN}) {
16549 next;
16550 }
16551 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016552 {
16553 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016554 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016555 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016556 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16557 my $DyLib = $Symbol_Library{1}{$Symbol};
16558 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016559 { # Symbol with Version
16560 $DyLib = $Symbol_Library{1}{$VSym};
16561 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016562 if(not $DyLib)
16563 { # const global data
16564 $DyLib = "";
16565 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016566 if($Level eq "Source" and $ReportFormat eq "html")
16567 { # do not show library name in HTML report
16568 $DyLib = "";
16569 }
16570 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16571 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016572 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016573 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16574 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016575 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016576 }
16577 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016578 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16579 {
16580 delete($SymbolChanges{$Symbol}{$Kind});
16581 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016582 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016583 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016584 }
16585 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016586 if(not keys(%{$SymbolChanges{$Symbol}})) {
16587 delete($SymbolChanges{$Symbol});
16588 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016589 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016590
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016591 if($ReportFormat eq "xml")
16592 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016593 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016594 {
16595 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016596 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016597 {
16598 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016599 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16600 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016601 {
16602 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16603 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16604 {
16605 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16606 {
16607 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016608 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016609
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016610 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16611 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16612 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16613 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16614 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016615 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16616 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16617 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016618 $INTERFACE_PROBLEMS .= " </problem>\n";
16619 }
16620 }
16621 $INTERFACE_PROBLEMS .= " </symbol>\n";
16622 }
16623 $INTERFACE_PROBLEMS .= " </library>\n";
16624 }
16625 $INTERFACE_PROBLEMS .= " </header>\n";
16626 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016627 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016628 }
16629 else
16630 { # HTML
16631 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016632 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016633 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016634 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016635 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016636 my (%NameSpaceSymbols, %NewSignature) = ();
16637 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016638 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016639 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016640 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016641 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016642 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016643 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 +040016644 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016645 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016646 my $Signature = get_Signature($Symbol, 1);
16647 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016648 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016649 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016650 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016651 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016652 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016653 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016654 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016655 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016656 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016657 }
16658 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16659 {
16660 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016661 $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 +040016662 $ProblemNum += 1;
16663 $ProblemsNum += 1;
16664 }
16665 }
16666 }
16667 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016668 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016669 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016670 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016671 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016672 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016673 }
16674 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016675 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016676 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016677 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16678 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16679 if($NewSignature{$Symbol})
16680 { # argument list changed to
16681 $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 +040016682 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016683 if($Symbol=~/\A(_Z|\?)/) {
16684 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16685 }
16686 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16687 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016688 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016689 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016690 }
16691 }
16692 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016693 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016694 }
16695 }
16696 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016697
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016698 if($INTERFACE_PROBLEMS)
16699 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016700 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16701 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16702 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016703 { # Safe Changes
16704 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016705 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016706 $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 +040016707 }
16708 }
16709 return $INTERFACE_PROBLEMS;
16710}
16711
16712sub get_Report_TypeProblems($$)
16713{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016714 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016715 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016716 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016717
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016718 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016719 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016720 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016721 {
16722 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16723 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016724 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016725 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016726 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016727 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016728 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016729
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016730 if($Severity eq "Safe"
16731 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016732 next;
16733 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016734
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016735 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16736 {
16737 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16738 { # select a problem with the highest priority
16739 next;
16740 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016741 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016742
16743 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016744 }
16745 }
16746 }
16747 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016748
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016749 my %Kinds_Locations = ();
16750 foreach my $TypeName (keys(%TypeChanges))
16751 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016752 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016753 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16754 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016755 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016756 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016757 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016758 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016759 { # other priority
16760 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16761 next;
16762 }
16763 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16764 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016765 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016766 { # duplicate target
16767 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16768 next;
16769 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016770 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016771 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016772 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016773 }
16774 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16775 delete($TypeChanges{$TypeName}{$Kind});
16776 }
16777 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016778 if(not keys(%{$TypeChanges{$TypeName}})) {
16779 delete($TypeChanges{$TypeName});
16780 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016781 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016782
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016783 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 +040016784 if($ReportFormat eq "xml")
16785 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016786 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016787 {
16788 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016789 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016790 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016791 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016792 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16793 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016794 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016795 {
16796 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16797 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16798 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16799 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16800 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16801 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016802 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16803 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16804 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016805 $TYPE_PROBLEMS .= " </problem>\n";
16806 }
16807 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016808 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016809 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016810 $TYPE_PROBLEMS .= showVTables($TypeName);
16811 }
16812 $TYPE_PROBLEMS .= " </type>\n";
16813 }
16814 $TYPE_PROBLEMS .= " </header>\n";
16815 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016816 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016817 }
16818 else
16819 { # HTML
16820 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016821 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016822 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016823 my (%NameSpace_Type) = ();
16824 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016825 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016826 }
16827 foreach my $NameSpace (sort keys(%NameSpace_Type))
16828 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016829 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016830 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 +040016831 foreach my $TypeName (@SortedTypes)
16832 {
16833 my $ProblemNum = 1;
16834 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016835
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016836 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16837 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016838 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016839 {
16840 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16841 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16842 {
16843 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
16844 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16845 $ProblemNum += 1;
16846 $ProblemsNum += 1;
16847 }
16848 }
16849 }
16850 $ProblemNum -= 1;
16851 if($TYPE_REPORT)
16852 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016853 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016854 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016855 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016856 $ShowVTables = showVTables($TypeName);
16857 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016858
16859 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016860 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16861 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16862 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16863 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016864 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016865 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016866 }
16867 }
16868 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016869 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016870 }
16871 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016872
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016873 if($TYPE_PROBLEMS)
16874 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016875 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16876 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016877 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016878 { # Safe Changes
16879 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016880 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016881 $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 +040016882 }
16883 }
16884 return $TYPE_PROBLEMS;
16885}
16886
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016887sub show_Type($$$)
16888{
16889 my ($Name, $Html, $LibVersion) = @_;
16890 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16891 $TType = lc($TType);
16892 if($TType=~/struct|union|enum/) {
16893 $Name=~s/\A\Q$TType\E //g;
16894 }
16895 if($Html) {
16896 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16897 }
16898 else {
16899 $Name = $TType." ".$Name;
16900 }
16901 return $Name;
16902}
16903
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016904sub get_Anchor($$$)
16905{
16906 my ($Kind, $Level, $Severity) = @_;
16907 if($JoinReport)
16908 {
16909 if($Severity eq "Safe") {
16910 return "Other_".$Level."_Changes_In_".$Kind."s";
16911 }
16912 else {
16913 return $Kind."_".$Level."_Problems_".$Severity;
16914 }
16915 }
16916 else
16917 {
16918 if($Severity eq "Safe") {
16919 return "Other_Changes_In_".$Kind."s";
16920 }
16921 else {
16922 return $Kind."_Problems_".$Severity;
16923 }
16924 }
16925}
16926
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016927sub showVTables($)
16928{
16929 my $TypeName = $_[0];
16930 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016931 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016932 if(defined $Type1{"VTable"}
16933 and keys(%{$Type1{"VTable"}}))
16934 {
16935 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016936 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016937 if(defined $Type2{"VTable"}
16938 and keys(%{$Type2{"VTable"}}))
16939 {
16940 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
16941 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016942 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016943 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016944 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
16945 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016946 }
16947 my $VTABLES = "";
16948 if($ReportFormat eq "xml")
16949 { # XML
16950 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016951 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016952 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016953 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016954 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
16955 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016956 $VTABLES .= " </entry>\n";
16957 }
16958 $VTABLES .= " </vtable>\n\n";
16959 }
16960 else
16961 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016962 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016963 $VTABLES .= "<tr><th>Offset</th>";
16964 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016965 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016966 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016967 {
16968 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016969 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016970 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016971 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016972 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016973 $Color1 = " class='failed'";
16974 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016975 }
16976 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016977 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016978 }
16979 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016980 $VTABLES .= "<tr><th>".$Index."</th>\n";
16981 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
16982 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016983 }
16984 $VTABLES .= "</table><br/>\n";
16985 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016986 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016987 }
16988 return $VTABLES;
16989 }
16990 }
16991 return "";
16992}
16993
16994sub simpleVEntry($)
16995{
16996 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016997 if(not defined $VEntry
16998 or $VEntry eq "") {
16999 return "";
17000 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017001
17002 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017003 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17004 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17005 if($VEntry=~/\A_ZThn.+\Z/) {
17006 $VEntry = "non-virtual thunk";
17007 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017008 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017009 # support for old GCC versions
17010 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17011 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17012 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017013 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17014 return $VEntry;
17015}
17016
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017017sub adjustParamPos($$$)
17018{
17019 my ($Pos, $Symbol, $LibVersion) = @_;
17020 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17021 {
17022 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17023 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17024 {
17025 return $Pos-1;
17026 }
17027
17028 return $Pos;
17029 }
17030
17031 return undef;
17032}
17033
17034sub getParamPos($$$)
17035{
17036 my ($Name, $Symbol, $LibVersion) = @_;
17037
17038 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17039 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17040 {
17041 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17042 foreach (keys(%{$Info->{"Param"}}))
17043 {
17044 if($Info->{"Param"}{$_}{"name"} eq $Name)
17045 {
17046 return $_;
17047 }
17048 }
17049 }
17050
17051 return undef;
17052}
17053
17054sub getParamName($)
17055{
17056 my $Loc = $_[0];
17057 $Loc=~s/\->.*//g;
17058 return $Loc;
17059}
17060
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017061sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017062{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017063 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017064 my $LIMIT = 10;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017065
17066 if(defined $AffectLimit)
17067 {
17068 $LIMIT = $AffectLimit;
17069 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017070
17071 my %SymSel = ();
17072 my %SymLocKind = ();
17073
17074 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017075 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017076 if(index($Symbol, "_Z")==0
17077 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017078 { # duplicated problems for C2 constructors, D2 and D0 destructors
17079 next;
17080 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017081
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017082 foreach my $Kind (sort keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017083 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017084 if(not defined $CompatProblems{$Level}{$Symbol}
17085 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17086 next;
17087 }
17088
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017089 foreach my $Loc (sort keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017090 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017091 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017092 next;
17093 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017094
17095 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17096 if($Level eq "Source")
17097 { # remove symbol version
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017098 $Symbol = $SN;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017099 }
17100
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017101 if($SV and defined $CompatProblems{$Level}{$SN}
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017102 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017103 { # duplicated problems for versioned symbols
17104 next;
17105 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017106
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017107 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017108 if($Type_Name ne $Target_TypeName) {
17109 next;
17110 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017111
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017112 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017113 }
17114 }
17115 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017116
17117 foreach my $Symbol (sort keys(%SymLocKind))
17118 {
17119 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17120 {
17121 foreach my $Kind (keys(%{$SymLocKind{$Symbol}{$Loc}}))
17122 {
17123 $SymSel{$Symbol}{"Loc"} = $Loc;
17124 $SymSel{$Symbol}{"Kind"} = $Kind;
17125
17126 last LOOP;
17127 }
17128 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017129 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017130
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017131 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017132 my $Num = 0;
17133
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017134 if($ReportFormat eq "xml")
17135 { # XML
17136 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017137
17138 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017139 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017140 my $PName = getParamName($Loc);
17141 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17142
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017143 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017144 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017145 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017146 $Target .= " param=\"$PName\"";
17147 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017148 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017149 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017150 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017151 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017152 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017153 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017154 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017155
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017156 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017157 $Target .= " field=\"$1\"";
17158 }
17159
17160 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017161 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017162 $Affected .= " </symbol>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017163
17164 if($Num>$LIMIT) {
17165 last LOOP;
17166 }
17167
17168 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017169 }
17170 $Affected .= " </affected>\n";
17171 }
17172 else
17173 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017174 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017175 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017176 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17177 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017178 my $PName = getParamName($SymSel{$Symbol}{"Loc"});
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017179 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17180
17181 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>";
17182 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
17183
17184 if($Num>$LIMIT) {
17185 last;
17186 }
17187
17188 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017189 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017190
17191 if(keys(%SymSel)>$LIMIT) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017192 $Affected .= " ...<br/>"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017193 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017194
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017195 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017196 if($Affected)
17197 {
17198 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017199 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymSel).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017200 }
17201 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017202
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017203 return $Affected;
17204}
17205
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017206sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017207{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017208 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017209 if($L2=~/\A(retval|this)\b/
17210 and $L1!~/\A(retval|this)\b/)
17211 {
17212 if($L1!~/\-\>/) {
17213 return 1;
17214 }
17215 elsif($L2=~/\-\>/) {
17216 return 1;
17217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017218 }
17219 return 0;
17220}
17221
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017222sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017223{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017224 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017225
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017226 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017227
17228 my $Location_I = $Location;
17229 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17230
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017231 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017232
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017233 if($Kind eq "Overridden_Virtual_Method"
17234 or $Kind eq "Overridden_Virtual_Method_B") {
17235 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17236 }
17237 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17238 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017239 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17240
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017241 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17242 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017243 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17244 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17245
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017246 if($ClassName eq $Problem{"Type_Name"}) {
17247 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17248 }
17249 else {
17250 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17251 }
17252 }
17253 else
17254 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017255 my $TypeID = undef;
17256
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017257 if($Location=~/retval/)
17258 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017259 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017260 push(@Sentence, "Field \'".$Location."\' in return value");
17261 }
17262 else {
17263 push(@Sentence, "Return value");
17264 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017265
17266 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017267 }
17268 elsif($Location=~/this/)
17269 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017270 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017271 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17272 }
17273 else {
17274 push(@Sentence, "\'this\' pointer");
17275 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017276
17277 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017278 }
17279 else
17280 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017281
17282 my $PName = getParamName($Location);
17283 my $PPos = getParamPos($PName, $Symbol, 1);
17284
17285 if(index($Location, "->")!=-1) {
17286 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017287 }
17288 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017289 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017290 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017291 if($PName) {
17292 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017293 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017294
17295 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17296 }
17297
17298 if($Location!~/this/)
17299 {
17300 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017301 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017302 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017303 push(@Sentence, "(pointer)");
17304 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017305 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017306 push(@Sentence, "(reference)");
17307 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017308 }
17309 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017310
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017311 if($Location eq "this") {
17312 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17313 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017314 else
17315 {
17316 my $Location_T = $Location;
17317 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17318
17319 my $TypeID_Problem = $TypeID;
17320 if($Location_T) {
17321 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17322 }
17323
17324 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17325 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17326 }
17327 else {
17328 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17329 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017330 }
17331 }
17332 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017333 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017334 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 +040017335 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017336
17337 my $Sent = join(" ", @Sentence);
17338
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017339 $Sent=~s/->/./g;
17340
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017341 if($ReportFormat eq "xml")
17342 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017343 $Sent=~s/'//g;
17344 }
17345
17346 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017347}
17348
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017349sub getFieldType($$$)
17350{
17351 my ($Location, $TypeId, $LibVersion) = @_;
17352
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017353 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017354
17355 foreach my $Name (@Fields)
17356 {
17357 my %Info = get_BaseType($TypeId, $LibVersion);
17358
17359 foreach my $Pos (keys(%{$Info{"Memb"}}))
17360 {
17361 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17362 {
17363 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17364 last;
17365 }
17366 }
17367 }
17368
17369 return $TypeId;
17370}
17371
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017372sub get_XmlSign($$)
17373{
17374 my ($Symbol, $LibVersion) = @_;
17375 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17376 my $Report = "";
17377 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17378 {
17379 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017380 my $Type = $Info->{"Param"}{$Pos}{"type"};
17381 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017382 foreach my $Typedef (keys(%ChangedTypedef))
17383 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017384 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17385 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17386 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017387 }
17388 $Report .= " <param pos=\"$Pos\">\n";
17389 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017390 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017391 $Report .= " </param>\n";
17392 }
17393 if(my $Return = $Info->{"Return"})
17394 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017395 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017396 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017397 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017398 $Report .= " </retval>\n";
17399 }
17400 return $Report;
17401}
17402
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017403sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017404{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017405 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017406 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017407 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017408 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017409 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17410 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017411 next;
17412 }
17413 $Report .= " <symbol name=\"$Symbol\">\n";
17414 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017415 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017416 {
17417 if(defined $CompleteSignature{1}{$Symbol}
17418 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17419 {
17420 $P1 = get_XmlSign($Symbol, 1);
17421 $S1 = get_Signature($Symbol, 1);
17422 }
17423 elsif($Symbol=~/\A(_Z|\?)/) {
17424 $S1 = $tr_name{$Symbol};
17425 }
17426 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017427 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017428 {
17429 if(defined $CompleteSignature{2}{$Symbol}
17430 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17431 {
17432 $P2 = get_XmlSign($Symbol, 2);
17433 $S2 = get_Signature($Symbol, 2);
17434 }
17435 elsif($Symbol=~/\A(_Z|\?)/) {
17436 $S2 = $tr_name{$Symbol};
17437 }
17438 }
17439 if($S1)
17440 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017441 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017442 $Report .= $P1;
17443 $Report .= " </old>\n";
17444 }
17445 if($S2 and $S2 ne $S1)
17446 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017447 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017448 $Report .= $P2;
17449 $Report .= " </new>\n";
17450 }
17451 $Report .= " </symbol>\n";
17452 }
17453 $Report .= "</symbols_info>\n";
17454 return $Report;
17455}
17456
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017457sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017458{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017459 my ($Level, $Report) = @_;
17460 if($ReportFormat eq "xml") {
17461 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017462 }
17463 if($StdOut)
17464 { # --stdout option
17465 print STDOUT $Report;
17466 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017467 else
17468 {
17469 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017470 mkpath(get_dirname($RPath));
17471
17472 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17473 print REPORT $Report;
17474 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017475 }
17476}
17477
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017478sub getReport($)
17479{
17480 my $Level = $_[0];
17481 if($ReportFormat eq "xml")
17482 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017483 if($Level eq "Join")
17484 {
17485 my $Report = "<reports>\n";
17486 $Report .= getReport("Binary");
17487 $Report .= getReport("Source");
17488 $Report .= "</reports>\n";
17489 return $Report;
17490 }
17491 else
17492 {
17493 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17494 my ($Summary, $MetaData) = get_Summary($Level);
17495 $Report .= $Summary."\n";
17496 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17497 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017498
17499 # additional symbols info (if needed)
17500 # $Report .= get_Report_SymbolsInfo($Level);
17501
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017502 $Report .= "</report>\n";
17503 return $Report;
17504 }
17505 }
17506 else
17507 { # HTML
17508 my $CssStyles = readModule("Styles", "Report.css");
17509 my $JScripts = readModule("Scripts", "Sections.js");
17510 if($Level eq "Join")
17511 {
17512 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17513 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017514 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
17515 my $Keywords = $TargetTitle.", compatibility, API, report";
17516 my $Description = "Compatibility report for the $TargetTitle $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017517 my ($BSummary, $BMetaData) = get_Summary("Binary");
17518 my ($SSummary, $SMetaData) = get_Summary("Source");
17519 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>";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017520 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017521 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017522 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17523 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017524 </div>";
17525 $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>";
17526 $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 Ponomarenko01e8e502015-08-21 22:08:40 +030017527 $Report .= getReportFooter("Double");
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017528 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017529 return $Report;
17530 }
17531 else
17532 {
17533 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017534 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17535 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17536 my $Description = "$Level compatibility report for the ".$TargetTitle." ".$TargetComponent." between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017537 if($Level eq "Binary")
17538 {
17539 if(getArch(1) eq getArch(2)
17540 and getArch(1) ne "unknown") {
17541 $Description .= " on ".showArch(getArch(1));
17542 }
17543 }
17544 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."\n<body>\n<div><a name='Top'></a>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017545 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017546 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17547 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17548 $Report .= get_SourceInfo();
17549 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017550 $Report .= getReportFooter("Single");
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017551 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017552 return $Report;
17553 }
17554 }
17555}
17556
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017557sub getLegend()
17558{
17559 return "<br/>
17560<table class='summary'>
17561<tr>
17562 <td class='new'>added</td>
17563 <td class='passed'>compatible</td>
17564</tr>
17565<tr>
17566 <td class='warning'>warning</td>
17567 <td class='failed'>incompatible</td>
17568</tr></table>\n";
17569}
17570
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017571sub createReport()
17572{
17573 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017574 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017575 writeReport("Join", getReport("Join"));
17576 }
17577 elsif($DoubleReport)
17578 { # default
17579 writeReport("Binary", getReport("Binary"));
17580 writeReport("Source", getReport("Source"));
17581 }
17582 elsif($BinaryOnly)
17583 { # --binary
17584 writeReport("Binary", getReport("Binary"));
17585 }
17586 elsif($SourceOnly)
17587 { # --source
17588 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017589 }
17590}
17591
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017592sub getReportFooter($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017593{
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017594 my $Type = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017595 my $Class = "footer";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017596
17597 if($Type eq "Double") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017598 $Class .= " double_report";
17599 }
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017600
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017601 my $Footer = "<div class=\'$Class\' align='right'><i>Generated on ".(localtime time);
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017602 $Footer .= " by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017603 $Footer .= "</i></div>";
17604 $Footer .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017605 return $Footer;
17606}
17607
17608sub get_Report_Problems($$)
17609{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017610 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017611
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017612 my $Report = get_Report_TypeProblems($Severity, $Level);
17613 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017614 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017615 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017616
17617 if($Severity eq "Low" or $Severity eq "Safe") {
17618 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017619 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017620
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017621 if($ReportFormat eq "html")
17622 {
17623 if($Report)
17624 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017625 if($JoinReport)
17626 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017627 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017628 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17629 }
17630 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017631 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017633 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017634 else
17635 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017636 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017637 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17638 }
17639 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017640 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017642 }
17643 }
17644 }
17645 return $Report;
17646}
17647
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017648sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017649{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017650 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17651 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17652 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17653 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017654 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17655 <meta name=\"keywords\" content=\"$Keywords\" />
17656 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017657 <title>
17658 $Title
17659 </title>
17660 <style type=\"text/css\">
17661 $Styles
17662 </style>
17663 <script type=\"text/javascript\" language=\"JavaScript\">
17664 <!--
17665 $Scripts
17666 -->
17667 </script>
17668 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017669}
17670
17671sub insertIDs($)
17672{
17673 my $Text = $_[0];
17674 while($Text=~/CONTENT_ID/)
17675 {
17676 if(int($Content_Counter)%2) {
17677 $ContentID -= 1;
17678 }
17679 $Text=~s/CONTENT_ID/c_$ContentID/;
17680 $ContentID += 1;
17681 $Content_Counter += 1;
17682 }
17683 return $Text;
17684}
17685
17686sub checkPreprocessedUnit($)
17687{
17688 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017689 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017690 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017691 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017692
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017693 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017694 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017695 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017696 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017697 chomp($Line);
17698 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017699 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017700 $CurHeader = path_format($1, $OSgroup);
17701 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017702 $CurClass = "";
17703
17704 if(index($CurHeader, $TMP_DIR)==0) {
17705 next;
17706 }
17707
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017708 if(substr($CurHeaderName, 0, 1) eq "<")
17709 { # <built-in>, <command-line>, etc.
17710 $CurHeaderName = "";
17711 $CurHeader = "";
17712 }
17713
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017714 if($ExtraInfo)
17715 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017716 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017717 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17718 }
17719 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017720 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017721 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017722 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017723 if($CurHeaderName)
17724 {
17725 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17726 and not $Registered_Headers{$Version}{$CurHeader})
17727 { # not a target
17728 next;
17729 }
17730 if(not is_target_header($CurHeaderName, 1)
17731 and not is_target_header($CurHeaderName, 2))
17732 { # user-defined header
17733 next;
17734 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017735 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017736 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017737
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017738 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017739 {
17740 my ($Name, $Value) = ($1, $2);
17741 if(not $Constants{$Version}{$Name}{"Access"})
17742 {
17743 $Constants{$Version}{$Name}{"Access"} = "public";
17744 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017745 if($CurHeaderName) {
17746 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17747 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017748 }
17749 }
17750 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17751 $Constants{$Version}{$1}{"Access"} = "private";
17752 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017753 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017754 else
17755 {
17756 if(defined $ExtraDump)
17757 {
17758 if($Line=~/(\w+)\s*\(/)
17759 { # functions
17760 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17761 }
17762 #elsif($Line=~/(\w+)\s*;/)
17763 #{ # data
17764 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17765 #}
17766 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17767 $CurClass = $2;
17768 }
17769 }
17770 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017771 }
17772 close(PREPROC);
17773 foreach my $Constant (keys(%{$Constants{$Version}}))
17774 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017775 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17776 {
17777 delete($Constants{$Version}{$Constant});
17778 next;
17779 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017780 if(not $ExtraDump and ($Constant=~/_h\Z/i
17781 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017782 { # skip
17783 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017784 }
17785 else {
17786 delete($Constants{$Version}{$Constant}{"Access"});
17787 }
17788 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017789 if($Debug)
17790 {
17791 mkpath($DEBUG_PATH{$Version});
17792 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17793 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017794}
17795
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017796sub uncoverConstant($$)
17797{
17798 my ($LibVersion, $Constant) = @_;
17799 return "" if(not $LibVersion or not $Constant);
17800 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17801 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17802 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17803 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017804
17805 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017806 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017807 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17808 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017809 {
17810 push(@RecurConstant, $Constant);
17811 my $Uncovered = uncoverConstant($LibVersion, $Value);
17812 if($Uncovered ne "") {
17813 $Value = $Uncovered;
17814 }
17815 pop(@RecurConstant);
17816 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017817
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017818 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017819 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017820 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17821 }
17822 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17823}
17824
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017825sub simpleConstant($$)
17826{
17827 my ($LibVersion, $Value) = @_;
17828 if($Value=~/\W/)
17829 {
17830 my $Value_Copy = $Value;
17831 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17832 {
17833 my $Word = $1;
17834 if($Value!~/$Word\s*\(/)
17835 {
17836 my $Val = uncoverConstant($LibVersion, $Word);
17837 if($Val ne "")
17838 {
17839 $Value=~s/\b$Word\b/$Val/g;
17840 }
17841 }
17842 }
17843 }
17844 return $Value;
17845}
17846
17847sub computeValue($)
17848{
17849 my $Value = $_[0];
17850
17851 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17852 return $1;
17853 }
17854
17855 if($Value=~/\A[\d\-\+()]+\Z/) {
17856 return eval($Value);
17857 }
17858
17859 return $Value;
17860}
17861
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017862my %IgnoreConstant = map {$_=>1} (
17863 "VERSION",
17864 "VERSIONCODE",
17865 "VERNUM",
17866 "VERS_INFO",
17867 "PATCHLEVEL",
17868 "INSTALLPREFIX",
17869 "VBUILD",
17870 "VPATCH",
17871 "VMINOR",
17872 "BUILD_STRING",
17873 "BUILD_TIME",
17874 "PACKAGE_STRING",
17875 "PRODUCTION",
17876 "CONFIGURE_COMMAND",
17877 "INSTALLDIR",
17878 "BINDIR",
17879 "CONFIG_FILE_PATH",
17880 "DATADIR",
17881 "EXTENSION_DIR",
17882 "INCLUDE_PATH",
17883 "LIBDIR",
17884 "LOCALSTATEDIR",
17885 "SBINDIR",
17886 "SYSCONFDIR",
17887 "RELEASE",
17888 "SOURCE_ID",
17889 "SUBMINOR",
17890 "MINOR",
17891 "MINNOR",
17892 "MINORVERSION",
17893 "MAJOR",
17894 "MAJORVERSION",
17895 "MICRO",
17896 "MICROVERSION",
17897 "BINARY_AGE",
17898 "INTERFACE_AGE",
17899 "CORE_ABI",
17900 "PATCH",
17901 "COPYRIGHT",
17902 "TIMESTAMP",
17903 "REVISION",
17904 "PACKAGE_TAG",
17905 "PACKAGEDATE",
17906 "NUMVERSION",
17907 "Release",
17908 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017909);
17910
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017911sub constantFilter($$$)
17912{
17913 my ($Name, $Value, $Level) = @_;
17914
17915 if($Level eq "Binary")
17916 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017917 if($Name=~/_t\Z/)
17918 { # __malloc_ptr_t
17919 return 1;
17920 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017921 foreach (keys(%IgnoreConstant))
17922 {
17923 if($Name=~/(\A|_)$_(_|\Z)/)
17924 { # version
17925 return 1;
17926 }
17927 if(/\A[A-Z].*[a-z]\Z/)
17928 {
17929 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17930 { # version
17931 return 1;
17932 }
17933 }
17934 }
17935 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17936 { # version
17937 return 1;
17938 }
17939 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17940 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17941 return 1;
17942 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017943
17944 if($Value=~/\A["'].*['"]/i)
17945 { # string
17946 return 0;
17947 }
17948
17949 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17950 { # static int gcry_pth_init
17951 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017952 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017953 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017954 return 1;
17955 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017956 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017957 { # foo(p)
17958 return 1;
17959 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017960 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017961 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017962 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017963 return 1;
17964 }
17965 }
17966
17967 return 0;
17968}
17969
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017970sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017971{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017972 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017973 foreach my $Constant (keys(%{$Constants{1}}))
17974 {
17975 if($SkipConstants{1}{$Constant})
17976 { # skipped by the user
17977 next;
17978 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017979
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017980 if(my $Header = $Constants{1}{$Constant}{"Header"})
17981 {
17982 if(not is_target_header($Header, 1)
17983 and not is_target_header($Header, 2))
17984 { # user-defined header
17985 next;
17986 }
17987 }
17988 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017989 next;
17990 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017991
17992 my $Old_Value = uncoverConstant(1, $Constant);
17993
17994 if(constantFilter($Constant, $Old_Value, $Level))
17995 { # separate binary and source problems
17996 next;
17997 }
17998
17999 if(not defined $Constants{2}{$Constant}{"Value"})
18000 { # removed
18001 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18002 "Target"=>$Constant,
18003 "Old_Value"=>$Old_Value );
18004 next;
18005 }
18006
18007 if($Constants{2}{$Constant}{"Value"} eq "")
18008 { # empty value
18009 # TODO: implement a rule
18010 next;
18011 }
18012
18013 my $New_Value = uncoverConstant(2, $Constant);
18014
18015 my $Old_Value_Pure = $Old_Value;
18016 my $New_Value_Pure = $New_Value;
18017
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018018 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18019 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18020 $New_Value_Pure=~s/(\W)\s+/$1/g;
18021 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018022
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018023 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018024
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018025 if($New_Value_Pure ne $Old_Value_Pure)
18026 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018027 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18028 { # complex values
18029 next;
18030 }
18031 if(computeValue($Old_Value) eq computeValue($New_Value))
18032 { # expressions
18033 next;
18034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018035 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18036 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18037 next;
18038 }
18039 if($Old_Value eq "0" and $New_Value eq "NULL")
18040 { # 0 => NULL
18041 next;
18042 }
18043 if($Old_Value eq "NULL" and $New_Value eq "0")
18044 { # NULL => 0
18045 next;
18046 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018047 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018048 "Target"=>$Constant,
18049 "Old_Value"=>$Old_Value,
18050 "New_Value"=>$New_Value );
18051 }
18052 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018053
18054 foreach my $Constant (keys(%{$Constants{2}}))
18055 {
18056 if(not defined $Constants{1}{$Constant}{"Value"})
18057 {
18058 if($SkipConstants{2}{$Constant})
18059 { # skipped by the user
18060 next;
18061 }
18062
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018063 if(my $Header = $Constants{2}{$Constant}{"Header"})
18064 {
18065 if(not is_target_header($Header, 1)
18066 and not is_target_header($Header, 2))
18067 { # user-defined header
18068 next;
18069 }
18070 }
18071 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018072 next;
18073 }
18074
18075 my $New_Value = uncoverConstant(2, $Constant);
18076 if(not defined $New_Value or $New_Value eq "") {
18077 next;
18078 }
18079
18080 if(constantFilter($Constant, $New_Value, $Level))
18081 { # separate binary and source problems
18082 next;
18083 }
18084
18085 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18086 "Target"=>$Constant,
18087 "New_Value"=>$New_Value );
18088 }
18089 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018090}
18091
18092sub convert_integer($)
18093{
18094 my $Value = $_[0];
18095 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018096 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018097 return hex($Value);
18098 }
18099 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018100 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018101 return oct($Value);
18102 }
18103 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018104 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018105 return oct($Value);
18106 }
18107 else {
18108 return $Value;
18109 }
18110}
18111
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018112sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018113{
18114 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018115 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018116 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018117 {
18118 if($LibVersion==1)
18119 {
18120 printMsg("WARNING", "checking headers only");
18121 $CheckHeadersOnly = 1;
18122 }
18123 else {
18124 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18125 }
18126 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018127
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018128 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018129 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018130 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018131
18132 if($CheckUndefined)
18133 {
18134 my %UndefinedLibs = ();
18135
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018136 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18137
18138 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018139 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018140 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018141 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018142 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018143 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018144 if($Symbol_Library{$LibVersion}{$Symbol}
18145 or $DepSymbol_Library{$LibVersion}{$Symbol})
18146 { # exported by target library
18147 next;
18148 }
18149 if(index($Symbol, '@')!=-1)
18150 { # exported default symbol version (@@)
18151 $Symbol=~s/\@/\@\@/;
18152 if($Symbol_Library{$LibVersion}{$Symbol}
18153 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18154 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018155 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018156 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018157 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18158 $UndefinedLibs{$Path} = 1;
18159 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018160 }
18161 }
18162 }
18163 if($ExtraInfo)
18164 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018165 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018166 {
18167 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018168 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018169 foreach (@Paths)
18170 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018171 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018172 my ($Dir, $Name) = separate_path($_);
18173
18174 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018175 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018176 }
18177
18178 $Name = parse_libname($Name, "name", $OStarget);
18179 $Name=~s/\Alib//;
18180
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018181 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018182 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018183
18184 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18185 {
18186 $LibString = " -L".esc($Dir).$LibString;
18187 }
18188
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018189 writeFile($ExtraInfo."/libs-string", $LibString);
18190 }
18191 }
18192 }
18193
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018194 if($ExtraInfo) {
18195 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18196 }
18197
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018198 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018199 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018200 if($#LibPaths!=-1)
18201 {
18202 if(not keys(%{$Symbol_Library{$LibVersion}}))
18203 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018204 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018205 printMsg("WARNING", "checking headers only");
18206 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018207 }
18208 }
18209 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018210
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018211 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018212 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018213}
18214
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018215my %Prefix_Lib_Map=(
18216 # symbols for autodetecting library dependencies (by prefix)
18217 "pthread_" => ["libpthread"],
18218 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18219 "cairo_" => ["libcairo"],
18220 "gtk_" => ["libgtk-x11-2.0"],
18221 "atk_" => ["libatk-1.0"],
18222 "gdk_" => ["libgdk-x11-2.0"],
18223 "gl" => ["libGL"],
18224 "glu" => ["libGLU"],
18225 "popt" => ["libpopt"],
18226 "Py" => ["libpython"],
18227 "jpeg_" => ["libjpeg"],
18228 "BZ2_" => ["libbz2"],
18229 "Fc" => ["libfontconfig"],
18230 "Xft" => ["libXft"],
18231 "SSL_" => ["libssl"],
18232 "sem_" => ["libpthread"],
18233 "snd_" => ["libasound"],
18234 "art_" => ["libart_lgpl_2"],
18235 "dbus_g" => ["libdbus-glib-1"],
18236 "GOMP_" => ["libgomp"],
18237 "omp_" => ["libgomp"],
18238 "cms" => ["liblcms"]
18239);
18240
18241my %Pattern_Lib_Map=(
18242 "SL[a-z]" => ["libslang"]
18243);
18244
18245my %Symbol_Lib_Map=(
18246 # symbols for autodetecting library dependencies (by name)
18247 "pow" => "libm",
18248 "fmod" => "libm",
18249 "sin" => "libm",
18250 "floor" => "libm",
18251 "cos" => "libm",
18252 "dlopen" => "libdl",
18253 "deflate" => "libz",
18254 "inflate" => "libz",
18255 "move_panel" => "libpanel",
18256 "XOpenDisplay" => "libX11",
18257 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018258 "clock_gettime" => "librt",
18259 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018260);
18261
18262sub find_SymbolLibs($$)
18263{
18264 my ($LibVersion, $Symbol) = @_;
18265
18266 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18267 { # debug symbols
18268 return ();
18269 }
18270
18271 my %Paths = ();
18272
18273 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18274 {
18275 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18276 $Paths{$Path} = 1;
18277 }
18278 }
18279
18280 if(my $SymbolPrefix = getPrefix($Symbol))
18281 {
18282 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18283 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18284 }
18285
18286 if(not keys(%Paths))
18287 {
18288 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18289 {
18290 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18291 {
18292 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18293 $Paths{$Path} = 1;
18294 }
18295 }
18296 }
18297 }
18298
18299 if(not keys(%Paths))
18300 {
18301 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18302 {
18303 if($Symbol=~/\A$Prefix/)
18304 {
18305 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18306 {
18307 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18308 $Paths{$Path} = 1;
18309 }
18310 }
18311 }
18312 }
18313 }
18314
18315 if(not keys(%Paths))
18316 {
18317 if($SymbolPrefix)
18318 { # try to find a library by symbol prefix
18319 if($SymbolPrefix eq "inotify" and
18320 index($Symbol, "\@GLIBC")!=-1)
18321 {
18322 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18323 $Paths{$Path} = 1;
18324 }
18325 }
18326 else
18327 {
18328 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18329 $Paths{$Path} = 1;
18330 }
18331 }
18332 }
18333 }
18334
18335 if(my @Paths = keys(%Paths)) {
18336 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18337 }
18338 }
18339 return keys(%Paths);
18340}
18341
18342sub get_LibPath_Prefix($$)
18343{
18344 my ($LibVersion, $Prefix) = @_;
18345
18346 $Prefix = lc($Prefix);
18347 $Prefix=~s/[_]+\Z//g;
18348
18349 foreach ("-2", "2", "-1", "1", "")
18350 { # libgnome-2.so
18351 # libxml2.so
18352 # libdbus-1.so
18353 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18354 return $Path;
18355 }
18356 }
18357 return "";
18358}
18359
18360sub getPrefix($)
18361{
18362 my $Str = $_[0];
18363 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18364 { # XmuValidArea: Xmu
18365 return $1;
18366 }
18367 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18368 { # snfReadFont: snf
18369 return $1;
18370 }
18371 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18372 { # XRRTimes: XRR
18373 return $1;
18374 }
18375 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18376 { # H5HF_delete: H5
18377 return $1;
18378 }
18379 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18380 { # alarm_event_add: alarm_
18381 return $1;
18382 }
18383 elsif($Str=~/\A(([a-z])\2{1,})/i)
18384 { # ffopen
18385 return $1;
18386 }
18387 return "";
18388}
18389
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018390sub getSymbolSize($$)
18391{ # size from the shared library
18392 my ($Symbol, $LibVersion) = @_;
18393 return 0 if(not $Symbol);
18394 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18395 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18396 {
18397 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18398 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18399 {
18400 if($Size<0) {
18401 return -$Size;
18402 }
18403 }
18404 }
18405 return 0;
18406}
18407
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018408sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018409{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18410 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018411 my ($Name, $Type) = @_;
18412
18413 # single
18414 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018415 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018416 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018417 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018418 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018419
18420 # double
18421 if($Name=~/$DEFAULT_STD_PARMS/)
18422 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018423 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018424 {
18425 my ($ShortName, $FuncParams) = split_Signature($Name);
18426
18427 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18428 {
18429 if(index($FParam, "<")!=-1)
18430 {
18431 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18432 my $FParam_N = canonifyName($FParam, "T");
18433 if($FParam_N ne $FParam) {
18434 $Name=~s/\Q$FParam\E/$FParam_N/g;
18435 }
18436 }
18437 }
18438 }
18439 elsif($Type eq "T")
18440 {
18441 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18442
18443 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018444 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018445 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018446 my $FParam = $TParams[0];
18447 foreach my $Pos (1 .. $#TParams)
18448 {
18449 my $TParam = $TParams[$Pos];
18450 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18451 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18452 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018453 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018454 }
18455 }
18456 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018457 if($Type eq "S") {
18458 return formatName($Name, "S");
18459 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018460 return $Name;
18461}
18462
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018463sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018464{
18465 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018466 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018467 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018468 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018469 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018470 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018471 next if($tr_name{$Symbol});
18472 $Symbol=~s/[\@\$]+(.*)\Z//;
18473 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018474 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018475 elsif(index($Symbol, "?")==0)
18476 {
18477 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018478 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018479 }
18480 else
18481 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018482 $tr_name{$Symbol} = $Symbol;
18483 $mangled_name_gcc{$Symbol} = $Symbol;
18484 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018485 }
18486 }
18487 if($#MnglNames1 > -1)
18488 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018489 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018490 foreach my $MnglName (@MnglNames1)
18491 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018492 if(my $Unmangled = pop(@UnmangledNames))
18493 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018494 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018495 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18496 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18497 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018498 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018499 and $tr_name{$MnglName}=~/vtable for (.+)/)
18500 { # bind class name and v-table symbol
18501 my $ClassName = $1;
18502 $ClassVTable{$ClassName} = $MnglName;
18503 $VTableClass{$MnglName} = $ClassName;
18504 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018505 }
18506 }
18507 }
18508 if($#MnglNames2 > -1)
18509 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018510 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018511 foreach my $MnglName (@MnglNames2)
18512 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018513 if(my $Unmangled = pop(@UnmangledNames))
18514 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018515 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018516 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018518 }
18519 }
18520 return \%tr_name;
18521}
18522
18523sub link_symbol($$$)
18524{
18525 my ($Symbol, $RunWith, $Deps) = @_;
18526 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18527 return 1;
18528 }
18529 if($Deps eq "+Deps")
18530 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018531 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018532 return 1;
18533 }
18534 }
18535 return 0;
18536}
18537
18538sub link_symbol_internal($$$)
18539{
18540 my ($Symbol, $RunWith, $Where) = @_;
18541 return 0 if(not $Where or not $Symbol);
18542 if($Where->{$RunWith}{$Symbol})
18543 { # the exact match by symbol name
18544 return 1;
18545 }
18546 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18547 { # indirect symbol version, i.e.
18548 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018549 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018550 if($Where->{$RunWith}{$VSym}) {
18551 return 1;
18552 }
18553 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018554 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018555 if($Sym and $Ver)
18556 { # search for the symbol with the same version
18557 # or without version
18558 if($Where->{$RunWith}{$Sym})
18559 { # old: foo@v|foo@@v
18560 # new: foo
18561 return 1;
18562 }
18563 if($Where->{$RunWith}{$Sym."\@".$Ver})
18564 { # old: foo|foo@@v
18565 # new: foo@v
18566 return 1;
18567 }
18568 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18569 { # old: foo|foo@v
18570 # new: foo@@v
18571 return 1;
18572 }
18573 }
18574 return 0;
18575}
18576
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018577sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018578{
18579 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018580 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018581 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018582 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018583 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018584 my $NM = get_CmdPath("nm");
18585 if(not $NM) {
18586 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018587 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018588 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018589 while(<APP>)
18590 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018591 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018592 push(@Imported, $1);
18593 }
18594 }
18595 close(APP);
18596 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018597 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018598 {
18599 my $DumpBinCmd = get_CmdPath("dumpbin");
18600 if(not $DumpBinCmd) {
18601 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18602 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018603 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018604 while(<APP>)
18605 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018606 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18607 push(@Imported, $1);
18608 }
18609 }
18610 close(APP);
18611 }
18612 else
18613 {
18614 my $ReadelfCmd = get_CmdPath("readelf");
18615 if(not $ReadelfCmd) {
18616 exitStatus("Not_Found", "can't find \"readelf\"");
18617 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018618 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018619 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018620 while(<APP>)
18621 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018622 if(defined $symtab)
18623 { # do nothing with symtab
18624 if(index($_, "'.dynsym'")!=-1)
18625 { # dynamic table
18626 $symtab = undef;
18627 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018628 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018629 elsif(index($_, "'.symtab'")!=-1)
18630 { # symbol table
18631 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018632 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018633 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018634 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018635 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18636 if($Ndx eq "UND")
18637 { # only imported symbols
18638 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018639 }
18640 }
18641 }
18642 close(APP);
18643 }
18644 return @Imported;
18645}
18646
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018647my %ELF_BIND = map {$_=>1} (
18648 "WEAK",
18649 "GLOBAL"
18650);
18651
18652my %ELF_TYPE = map {$_=>1} (
18653 "FUNC",
18654 "IFUNC",
18655 "OBJECT",
18656 "COMMON"
18657);
18658
18659my %ELF_VIS = map {$_=>1} (
18660 "DEFAULT",
18661 "PROTECTED"
18662);
18663
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018664sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018665{ # read the line of 'readelf' output corresponding to the symbol
18666 my @Info = split(/\s+/, $_[0]);
18667 # Num: Value Size Type Bind Vis Ndx Name
18668 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018669 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018670 shift(@Info); # spaces
18671 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018672
18673 if($#Info==7)
18674 { # UND SYMBOL (N)
18675 if($Info[7]=~/\(\d+\)/) {
18676 pop(@Info);
18677 }
18678 }
18679
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018680 if($#Info!=6)
18681 { # other lines
18682 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018683 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018684 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018685 return () if(not defined $ELF_BIND{$Info[3]});
18686 return () if(not defined $ELF_VIS{$Info[4]});
18687 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18688 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18689 return ();
18690 }
18691 if($OStarget eq "symbian")
18692 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18693 if(index($Info[6], "_._.absent_export_")!=-1)
18694 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18695 return ();
18696 }
18697 $Info[6]=~s/\@.+//g; # remove version
18698 }
18699 if(index($Info[2], "0x") == 0)
18700 { # size == 0x3d158
18701 $Info[2] = hex($Info[2]);
18702 }
18703 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018704}
18705
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018706sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018707{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018708 my ($LibVersion, $Name) = @_;
18709 return "" if(not $LibVersion or not $Name);
18710 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18711 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018712 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018713 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18714}
18715
18716sub get_LibPath_I($$)
18717{
18718 my ($LibVersion, $Name) = @_;
18719 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018720 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018721 if(-f $Name)
18722 { # absolute path
18723 return $Name;
18724 }
18725 else
18726 { # broken
18727 return "";
18728 }
18729 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018730 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018731 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018732 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018733 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018734 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018735 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018736 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018737 }
18738 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18739 { # ldconfig default paths
18740 return $DefaultPath;
18741 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018742 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018743 { # search in default linker directories
18744 # and then in all system paths
18745 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018746 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018747 }
18748 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018749 if(not defined $Cache{"checkSystemFiles"}) {
18750 checkSystemFiles();
18751 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018752 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18753 return $AllObjects[0];
18754 }
18755 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18756 {
18757 if($ShortName ne $Name)
18758 { # FIXME: check this case
18759 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18760 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018761 }
18762 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018763 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018764 # can't find
18765 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018766}
18767
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018768sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018769{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018770 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18771 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018772
18773 my $Real_Path = realpath($Lib_Path);
18774
18775 if(not $Real_Path)
18776 { # broken link
18777 return ();
18778 }
18779
18780 my $Lib_Name = get_filename($Real_Path);
18781
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018782 if($ExtraInfo)
18783 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018784 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018785 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018786 }
18787
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018788 if($IsNeededLib)
18789 {
18790 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18791 return ();
18792 }
18793 }
18794 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018795 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018796
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018797 push(@RecurLib, $Lib_Name);
18798 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018799 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18800
18801 if(not $IsNeededLib)
18802 { # special cases: libstdc++ and libc
18803 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18804 {
18805 if($ShortName eq "libstdc++")
18806 { # libstdc++.so.6
18807 $STDCXX_TESTING = 1;
18808 }
18809 elsif($ShortName eq "libc")
18810 { # libc-2.11.3.so
18811 $GLIBC_TESTING = 1;
18812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018813 }
18814 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018815 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018816 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018817 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018818 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018819 mkpath(get_dirname($DebugPath));
18820 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018821 if($OStarget eq "macos")
18822 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018823 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018824 if(not $NM) {
18825 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018826 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018827 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018828 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018829 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018830 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018831 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018832 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018833 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018834 else
18835 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018836 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018837 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018838 while(<LIB>)
18839 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018840 if($CheckUndefined)
18841 {
18842 if(not $IsNeededLib)
18843 {
18844 if(/ U _([\w\$]+)\s*\Z/)
18845 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018846 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018847 next;
18848 }
18849 }
18850 }
18851
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018852 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018853 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018854 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018855 if($IsNeededLib)
18856 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018857 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018858 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018859 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18860 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018861 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018862 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018863 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018864 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018865 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18866 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018867 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18868 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018869 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018870 setLanguage($LibVersion, "C++");
18871 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018872 }
18873 if($CheckObjectsOnly
18874 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018875 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018876 }
18877 }
18878 }
18879 }
18880 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018881
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018882 if($Deps)
18883 {
18884 if($LIB_TYPE eq "dynamic")
18885 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018886
18887 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018888 if(not $OtoolCmd) {
18889 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018890 }
18891
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018892 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18893 while(<LIB>)
18894 {
18895 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18896 and $1 ne $Lib_Path) {
18897 $NeededLib{$1} = 1;
18898 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018899 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018900 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018901 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018902 }
18903 }
18904 elsif($OStarget eq "windows")
18905 { # Windows *.dll, *.lib
18906 my $DumpBinCmd = get_CmdPath("dumpbin");
18907 if(not $DumpBinCmd) {
18908 exitStatus("Not_Found", "can't find \"dumpbin\"");
18909 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018910 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018911 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018912 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018913 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018914 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018915 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018916 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018917 else
18918 { # write to pipe
18919 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018920 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018921 while(<LIB>)
18922 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18923 # 1198 4AD SetThreadToken (forwarded to ...)
18924 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018925 # 1 0 00005B30 ??0?N = ... (with pdb)
18926 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018927 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018928 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018929 { # dynamic, static and forwarded symbols
18930 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018931 if($IsNeededLib)
18932 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018933 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018934 {
18935 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18936 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18937 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018938 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018939 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018940 {
18941 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18942 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018943 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18944 {
18945 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18946 setLanguage($LibVersion, "C++");
18947 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018948 }
18949 if($CheckObjectsOnly
18950 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018951 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018952 }
18953 }
18954 }
18955 }
18956 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018957
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018958 if($Deps)
18959 {
18960 if($LIB_TYPE eq "dynamic")
18961 { # dependencies
18962 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18963 while(<LIB>)
18964 {
18965 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
18966 and $1 ne $Lib_Path) {
18967 $NeededLib{path_format($1, $OSgroup)} = 1;
18968 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018969 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018970 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018971 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018972 }
18973 }
18974 else
18975 { # Unix; *.so, *.a
18976 # Symbian: *.dso, *.lib
18977 my $ReadelfCmd = get_CmdPath("readelf");
18978 if(not $ReadelfCmd) {
18979 exitStatus("Not_Found", "can't find \"readelf\"");
18980 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018981 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018982 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018983 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018984 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018985 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018986 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018987 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018988 else
18989 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018990 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018991 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018992 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018993 while(<LIB>)
18994 {
18995 if($LIB_TYPE eq "dynamic")
18996 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018997 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018998 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018999 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019000 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019001 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019002 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019003 # do nothing with symtab
19004 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019005 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019006 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019007 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019008 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019009 next;
19010 }
19011 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019012 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019013 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019014 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019015 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019016 if($CheckUndefined)
19017 {
19018 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019019 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019020 }
19021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019022 next;
19023 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019024 if($Bind eq "WEAK")
19025 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019026 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019027 if($Weak eq "-Weak")
19028 { # skip WEAK symbols
19029 next;
19030 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019031 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019032 my $Short = $Symbol;
19033 $Short=~s/\@.+//g;
19034 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019035 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019036 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19037 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019038 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019039 if($IsNeededLib)
19040 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019041 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019042 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019043 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19044 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019046 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019047 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019048 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019049 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19050 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19051 if($Vers)
19052 {
19053 if($LIB_EXT eq "so")
19054 { # value
19055 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19056 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19057 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019058 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019059 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19060 {
19061 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19062 setLanguage($LibVersion, "C++");
19063 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019064 }
19065 if($CheckObjectsOnly
19066 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019067 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019068 }
19069 }
19070 }
19071 }
19072 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019073
19074 if($Deps and $LIB_TYPE eq "dynamic")
19075 { # dynamic library specifics
19076 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19077 open(LIB, $Cmd." |");
19078
19079 while(<LIB>)
19080 {
19081 if(/NEEDED.+\[([^\[\]]+)\]/)
19082 { # dependencies:
19083 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19084 $NeededLib{$1} = 1;
19085 }
19086 }
19087
19088 close(LIB);
19089 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019090 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019091 if($Vers)
19092 {
19093 if(not $IsNeededLib and $LIB_EXT eq "so")
19094 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019095 my %Found = ();
19096
19097 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019098 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019099 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019100 next if(index($Symbol,"\@")==-1);
19101 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019102 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019103 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019104 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019105 if($Symbol_SameValue ne $Symbol
19106 and index($Symbol_SameValue,"\@")==-1)
19107 {
19108 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019109 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019110 last;
19111 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019112 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019113 }
19114 }
19115
19116 # default
19117 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19118 {
19119 next if(defined $Found{$Symbol});
19120 next if(index($Symbol,"\@\@")==-1);
19121
19122 if($Symbol=~/\A([^\@]*)\@\@/
19123 and not $SymVer{$LibVersion}{$1})
19124 {
19125 $SymVer{$LibVersion}{$1} = $Symbol;
19126 $Found{$Symbol} = 1;
19127 }
19128 }
19129
19130 # non-default
19131 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19132 {
19133 next if(defined $Found{$Symbol});
19134 next if(index($Symbol,"\@")==-1);
19135
19136 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19137 and not $SymVer{$LibVersion}{$1})
19138 {
19139 $SymVer{$LibVersion}{$1} = $Symbol;
19140 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019141 }
19142 }
19143 }
19144 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019145 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019146 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019147 foreach my $DyLib (sort keys(%NeededLib))
19148 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019149 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19150
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019151 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19152 {
19153 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19154 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19155 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019156 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019157 }
19158 }
19159 pop(@RecurLib);
19160 return $Library_Symbol{$LibVersion};
19161}
19162
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019163sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019164{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019165 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019166 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019167 return keys(%Prefixes);
19168}
19169
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019170sub get_prefixes_I($$)
19171{
19172 foreach my $P (@{$_[0]})
19173 {
19174 my @Parts = reverse(split(/[\/\\]+/, $P));
19175 my $Name = $Parts[0];
19176 foreach (1 .. $#Parts)
19177 {
19178 $_[1]->{$Name}{$P} = 1;
19179 last if($_>4 or $Parts[$_] eq "include");
19180 $Name = $Parts[$_].$SLASH.$Name;
19181 }
19182 }
19183}
19184
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019185sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019186{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019187 $Cache{"checkSystemFiles"} = 1;
19188
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019189 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019190
19191 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019192 {
19193 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019194
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019195 my @Files = cmd_find($DevelPath,"f");
19196 foreach my $Link (cmd_find($DevelPath,"l"))
19197 { # add symbolic links
19198 if(-f $Link) {
19199 push(@Files, $Link);
19200 }
19201 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019202
19203 if(not $CheckObjectsOnly)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019204 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019205 # search for headers in /usr/lib
Andrey Ponomarenko13bb0332013-06-28 15:32:28 +040019206 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19207 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19208 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019209 }
19210
19211 # search for libraries in /usr/lib (including symbolic links)
19212 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19213 foreach my $Path (@Libs)
19214 {
19215 my $N = get_filename($Path);
19216 $SystemObjects{$N}{$Path} = 1;
19217 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019218 }
19219 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019220
19221 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019222 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019223 foreach my $DevelPath (@{$SystemPaths{"include"}})
19224 {
19225 next if(not -d $DevelPath);
19226 # search for all header files in the /usr/include
19227 # with or without extension (ncurses.h, QtCore, ...)
19228 push(@SysHeaders, cmd_find($DevelPath,"f"));
19229 foreach my $Link (cmd_find($DevelPath,"l"))
19230 { # add symbolic links
19231 if(-f $Link) {
19232 push(@SysHeaders, $Link);
19233 }
19234 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019235 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019236 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019237 }
19238}
19239
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019240sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019241{
19242 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019243 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019244 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19245 {
19246 if(not -e $Dest) {
19247 exitStatus("Access_Error", "can't access \'$Dest\'");
19248 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019249 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019250 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19251 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019252 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019253 }
19254 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019255 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019256}
19257
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019258sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019259{
19260 my ($Path, $LibVersion) = @_;
19261 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019262 my $Name = get_filename($Path);
19263 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019264 return 1;
19265 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019266 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019267 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19268 return 1;
19269 }
19270 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19271 {
19272 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19273 return 1;
19274 }
19275 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019276 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019277 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019278 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019279 return 1;
19280 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019281 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019282 return 1;
19283 }
19284 }
19285 return 0;
19286}
19287
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019288sub specificHeader($$)
19289{
19290 my ($Header, $Spec) = @_;
19291 my $Name = get_filename($Header);
19292
19293 if($Spec eq "windows")
19294 {# MS Windows
19295 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19296 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19297 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19298 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19299 my @Dirs = (
19300 "win32",
19301 "win64",
19302 "win",
19303 "windows",
19304 "msvcrt"
19305 ); # /gsf-win32/
19306 if(my $DIRs = join("|", @Dirs)) {
19307 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19308 }
19309 }
19310 elsif($Spec eq "macos")
19311 { # Mac OS
19312 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19313 }
19314
19315 return 0;
19316}
19317
19318sub skipAlienHeader($)
19319{
19320 my $Path = $_[0];
19321 my $Name = get_filename($Path);
19322 my $Dir = get_dirname($Path);
19323
19324 if($Tolerance=~/2/)
19325 { # 2 - skip internal headers
19326 my @Terms = (
19327 "p",
19328 "priv",
19329 "int",
19330 "impl",
19331 "implementation",
19332 "internal",
19333 "private",
19334 "old",
19335 "compat",
19336 "debug",
19337 "test",
19338 "gen"
19339 );
19340
19341 my @Dirs = (
19342 "private",
19343 "priv",
19344 "port",
19345 "impl",
19346 "internal",
19347 "detail",
19348 "details",
19349 "old",
19350 "compat",
19351 "debug",
19352 "config",
19353 "compiler",
19354 "platform",
19355 "test"
19356 );
19357
19358 if(my $TERMs = join("|", @Terms)) {
19359 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19360 }
19361 if(my $DIRs = join("|", @Dirs)) {
19362 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19363 }
19364
19365 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19366 }
19367
19368 if($Tolerance=~/1/)
19369 { # 1 - skip non-Linux headers
19370 if($OSgroup ne "windows")
19371 {
19372 if(specificHeader($Path, "windows")) {
19373 return 1;
19374 }
19375 }
19376 if($OSgroup ne "macos")
19377 {
19378 if(specificHeader($Path, "macos")) {
19379 return 1;
19380 }
19381 }
19382 }
19383
19384 # valid
19385 return 0;
19386}
19387
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019388sub skipHeader($$)
19389{
19390 my ($Path, $LibVersion) = @_;
19391 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019392 if(defined $Cache{"skipHeader"}{$Path}) {
19393 return $Cache{"skipHeader"}{$Path};
19394 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019395 if(defined $Tolerance and $Tolerance=~/1|2/)
19396 { # --tolerant
19397 if(skipAlienHeader($Path)) {
19398 return ($Cache{"skipHeader"}{$Path} = 1);
19399 }
19400 }
19401 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19402 return 0;
19403 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019404 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19405}
19406
19407sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019408{ # returns:
19409 # 1 - if header should NOT be included and checked
19410 # 2 - if header should NOT be included, but should be checked
19411 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019412 my $Name = get_filename($Path);
19413 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019414 return $Kind;
19415 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019416 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19417 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019418 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019419 if(index($Path, $D)!=-1)
19420 {
19421 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19422 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19423 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019424 }
19425 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019426 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19427 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019428 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019429 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19430 {
19431 if($Name=~/$P/) {
19432 return $Kind;
19433 }
19434 if($P=~/[\/\\]/ and $Path=~/$P/) {
19435 return $Kind;
19436 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019437 }
19438 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019439
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019440 return 0;
19441}
19442
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019443sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019444{
19445 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019446 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019447 { # system directory
19448 return;
19449 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019450 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019451 { # already registered
19452 return;
19453 }
19454 foreach my $Path (find_libs($Dir,"",1))
19455 {
19456 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019457 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019458 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019459 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019460 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19461}
19462
19463sub registerObject($$)
19464{
19465 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019466
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019467 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019468 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019469 if($OStarget=~/linux|bsd/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019470 {
19471 if(my $SONAME = getSONAME($Path)) {
19472 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19473 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019474 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019475 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19476 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019477 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019478
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019479 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019480 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019481 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019482 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019483 if($ObjArch ne getArch_GCC($LibVersion))
19484 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19485 $CheckedArch{$LibVersion} = 1;
19486 printMsg("WARNING", "the architectures of input objects and the used GCC compiler are not equal, please change the compiler by --gcc-path=PATH option.");
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019487 }
19488 }
19489 }
19490}
19491
19492sub getArch_Object($)
19493{
19494 my $Path = $_[0];
19495
19496 my %MachineType = (
19497 "14C" => "x86",
19498 "8664" => "x86_64",
19499 "1C0" => "arm",
19500 "200" => "ia64"
19501 );
19502
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019503 my %ArchName = (
19504 "s390:31-bit" => "s390",
19505 "s390:64-bit" => "s390x",
19506 "powerpc:common" => "ppc32",
19507 "powerpc:common64" => "ppc64",
19508 "i386:x86-64" => "x86_64",
19509 "mips:3000" => "mips",
19510 "sparc:v8plus" => "sparcv9"
19511 );
19512
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019513 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019514 {
19515 my $DumpbinCmd = get_CmdPath("dumpbin");
19516 if(not $DumpbinCmd) {
19517 exitStatus("Not_Found", "can't find \"dumpbin\"");
19518 }
19519
19520 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19521 my $Out = `$Cmd`;
19522
19523 if($Out=~/(\w+)\smachine/)
19524 {
19525 if(my $Type = $MachineType{uc($1)})
19526 {
19527 return $Type;
19528 }
19529 }
19530 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019531 elsif($OStarget=~/linux|bsd/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019532 {
19533 my $ObjdumpCmd = get_CmdPath("objdump");
19534 if(not $ObjdumpCmd) {
19535 exitStatus("Not_Found", "can't find \"objdump\"");
19536 }
19537
19538 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019539
19540 if($OSgroup eq "windows") {
19541 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19542 }
19543 else {
19544 $Cmd = "LANG=$LOCALE ".$Cmd;
19545 }
19546 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019547
19548 if($Out=~/architecture:\s+([\w\-\:]+)/)
19549 {
19550 my $Arch = $1;
19551 if($Arch=~s/\:(.+)//)
19552 {
19553 my $Suffix = $1;
19554
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019555 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019556 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019557 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019558 }
19559 }
19560
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019561 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019562 $Arch = "x86";
19563 }
19564
19565 if($Arch eq "x86-64") {
19566 $Arch = "x86_64";
19567 }
19568
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019569 if($Arch eq "ia64-elf64") {
19570 $Arch = "ia64";
19571 }
19572
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019573 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019574 }
19575 }
19576 else
19577 { # macos, etc.
19578 # TODO
19579 }
19580
19581 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019582}
19583
19584sub getSONAME($)
19585{
19586 my $Path = $_[0];
19587 return if(not $Path);
19588 if(defined $Cache{"getSONAME"}{$Path}) {
19589 return $Cache{"getSONAME"}{$Path};
19590 }
19591 my $ObjdumpCmd = get_CmdPath("objdump");
19592 if(not $ObjdumpCmd) {
19593 exitStatus("Not_Found", "can't find \"objdump\"");
19594 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019595 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019596 if($OSgroup eq "windows") {
19597 $SonameCmd .= " | find \"SONAME\"";
19598 }
19599 else {
19600 $SonameCmd .= " | grep SONAME";
19601 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019602 if(my $SonameInfo = `$SonameCmd`)
19603 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019604 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19605 return ($Cache{"getSONAME"}{$Path} = $1);
19606 }
19607 }
19608 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019609}
19610
19611sub getSOPaths_Dest($$)
19612{
19613 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019614 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019615 return ();
19616 }
19617 if(-f $Dest)
19618 {
19619 if(not parse_libname($Dest, "name", $OStarget)) {
19620 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19621 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019622 registerObject($Dest, $LibVersion);
19623 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019624 return ($Dest);
19625 }
19626 elsif(-d $Dest)
19627 {
19628 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019629 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019630 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019631 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19632 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019633 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019634 { # all files and symlinks that match the name of a library
19635 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19636 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019637 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019638 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019639 }
19640 }
19641 }
19642 else
19643 { # search for all files and symlinks
19644 foreach my $Path (find_libs($Dest,"",""))
19645 {
19646 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019647 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019648 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019649 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019650 }
19651 if($OSgroup eq "macos")
19652 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019653 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019654 {
19655 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019656 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019657 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019658 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19659 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019660 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019661 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019662 }
19663 }
19664 }
19665 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019666 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019667 }
19668 else {
19669 return ();
19670 }
19671}
19672
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019673sub isCyclical($$)
19674{
19675 my ($Stack, $Value) = @_;
19676 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019677}
19678
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019679sub getGCC_Opts($)
19680{ # to use in module
19681 my $LibVersion = $_[0];
19682
19683 my @Opts = ();
19684
19685 if($CompilerOptions{$LibVersion})
19686 { # user-defined options
19687 push(@Opts, $CompilerOptions{$LibVersion});
19688 }
19689 if($GccOptions)
19690 { # additional
19691 push(@Opts, $GccOptions);
19692 }
19693
19694 if(@Opts) {
19695 return join(" ", @Opts);
19696 }
19697
19698 return undef;
19699}
19700
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019701sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019702{
19703 my $LibVersion = $_[0];
19704
19705 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19706 return $Cache{"getArch_GCC"}{$LibVersion};
19707 }
19708
19709 my $Arch = undef;
19710
19711 if($GCC_PATH)
19712 {
19713 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19714
19715 my $Cmd = $GCC_PATH." test.c -o test";
19716 if(my $Opts = getGCC_Opts($LibVersion))
19717 { # user-defined options
19718 $Cmd .= " ".$Opts;
19719 }
19720
19721 chdir($TMP_DIR);
19722 system($Cmd);
19723 chdir($ORIG_DIR);
19724
19725 $Arch = getArch_Object("$TMP_DIR/test");
19726
19727 unlink("$TMP_DIR/test.c");
19728 unlink("$TMP_DIR/test");
19729 }
19730
19731 if(not $Arch) {
19732 exitStatus("Error", "can't check ARCH type");
19733 }
19734
19735 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19736}
19737
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019738sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019739{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019740 my $LibVersion = $_[0];
19741
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019742 my $Size = undef;
19743
19744 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019745 if(my $Arch = getArch($LibVersion))
19746 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019747 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019748 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019749 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019750 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19751 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019752 }
19753 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019754
19755 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019756 {
19757 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019758
19759 my $Cmd = $GCC_PATH." -E -dD empty.h";
19760 if(my $Opts = getGCC_Opts($LibVersion))
19761 { # user-defined options
19762 $Cmd .= " ".$Opts;
19763 }
19764
19765 chdir($TMP_DIR);
19766 my $Defines = `$Cmd`;
19767 chdir($ORIG_DIR);
19768
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019769 unlink("$TMP_DIR/empty.h");
19770
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019771 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19772 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019773 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019774 }
19775 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19776 { # GCC 3
19777 my $PTRDIFF = $1;
19778 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019779 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019780 }
19781 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019782 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019783 }
19784 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019785 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019786
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019787 if(not $Size) {
19788 exitStatus("Error", "can't check WORD size");
19789 }
19790
19791 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019792}
19793
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019794sub getWordSize($)
19795{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019796 return $WORD_SIZE{$_[0]};
19797}
19798
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019799sub majorVersion($)
19800{
19801 my $V = $_[0];
19802 return 0 if(not $V);
19803 my @VParts = split(/\./, $V);
19804 return $VParts[0];
19805}
19806
19807sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019808{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019809 my ($V1, $V2) = @_;
19810 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019811 my @V1Parts = split(/\./, $V1);
19812 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019813 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19814 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019815 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19816 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19817 }
19818 return -1 if($#V1Parts < $#V2Parts);
19819 return 1 if($#V1Parts > $#V2Parts);
19820 return 0;
19821}
19822
19823sub read_ABI_Dump($$)
19824{
19825 my ($LibVersion, $Path) = @_;
19826 return if(not $LibVersion or not -e $Path);
19827 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019828 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019829 { # input *.abi
19830 $FilePath = $Path;
19831 }
19832 else
19833 { # input *.abi.tar.gz
19834 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019835 if(not isDump_U($FilePath)) {
19836 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19837 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019838 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019839
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019840 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019841
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019842 my $Line = readLineNum($FilePath, 0);
19843 if($Line=~/xml/)
19844 { # XML format
19845 loadModule("XmlDump");
19846 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019847 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019848 else
19849 { # Perl Data::Dumper format (default)
19850 open(DUMP, $FilePath);
19851 local $/ = undef;
19852 my $Content = <DUMP>;
19853 close(DUMP);
19854
19855 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19856 { # remove temp file
19857 unlink($FilePath);
19858 }
19859 if($Content!~/};\s*\Z/) {
19860 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19861 }
19862 $ABI = eval($Content);
19863 if(not $ABI) {
19864 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19865 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019866 }
19867 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019868 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019869 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019870 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019871 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019872 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019873 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019874 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030019875 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019876
19877 if($ABI->{"ABI_DUMP_VERSION"})
19878 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019879 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019880 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019881 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019882 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019883 }
19884 else
19885 { # support for old ABI dumps
19886 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019887 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019888 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019889 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019890 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019891
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019892 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019893 {
19894 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019895 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019896
19897 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19898 { # DWARF ABI Dump
19899 $UseConv_Real{$LibVersion}{"P"} = 1;
19900 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19901
19902 $UsedDump{$LibVersion}{"DWARF"} = 1;
19903
19904 $TargetComponent = "module";
19905 }
19906
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019907 if(not checkDump($LibVersion, "2.11"))
19908 { # old ABI dumps
19909 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019910 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019911 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019912 { # ABI dump created with --binary option
19913 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19914 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019915 else
19916 { # default
19917 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19918 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019919
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019920 if(defined $ABI->{"Mode"}
19921 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019922 { # --ext option
19923 $ExtendedCheck = 1;
19924 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019925 if($ABI->{"Extra"}) {
19926 $ExtraDump = 1;
19927 }
19928
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019929 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019930 {
19931 $UsedDump{$LibVersion}{"L"} = $Lang;
19932 setLanguage($LibVersion, $Lang);
19933 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019934 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019935 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019936 }
19937 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019938 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019939 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019940 if(not $TInfo)
19941 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019942 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019943 }
19944 my %Tid_TDid = ();
19945 foreach my $TDid (keys(%{$TInfo}))
19946 {
19947 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19948 {
19949 $MAX_ID = $Tid if($Tid>$MAX_ID);
19950 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019951 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019952 }
19953 }
19954 my %NewID = ();
19955 foreach my $Tid (keys(%Tid_TDid))
19956 {
19957 my @TDids = keys(%{$Tid_TDid{$Tid}});
19958 if($#TDids>=1)
19959 {
19960 foreach my $TDid (@TDids)
19961 {
19962 if($TDid) {
19963 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19964 }
19965 else
19966 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019967 my $ID = ++$MAX_ID;
19968
19969 $NewID{$TDid}{$Tid} = $ID;
19970 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19971 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019972 }
19973 }
19974 }
19975 else
19976 {
19977 my $TDid = $TDids[0];
19978 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19979 }
19980 }
19981 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
19982 {
19983 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
19984 if(defined $Info{"BaseType"})
19985 {
19986 my $Bid = $Info{"BaseType"}{"Tid"};
19987 my $BDid = $Info{"BaseType"}{"TDid"};
19988 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019989 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019990 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
19991 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
19992 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019993 }
19994 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
19995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019996 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019997 read_Machine_DumpInfo($ABI, $LibVersion);
19998 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019999 if(not $SymbolInfo{$LibVersion})
20000 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020001 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020002 }
20003 if(not keys(%{$SymbolInfo{$LibVersion}}))
20004 { # validation of old-version dumps
20005 if(not $ExtendedCheck) {
20006 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20007 }
20008 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020009 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020010 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020011 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020012 else
20013 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020014 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020015 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020016 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020017 }
20018 if(not $DepSymbols)
20019 { # Cannot reconstruct DepSymbols. This may result in false
20020 # positives if the old dump is for library 2. Not a problem if
20021 # old dumps are only from old libraries.
20022 $DepSymbols = {};
20023 }
20024 foreach my $Symbol (keys(%{$DepSymbols})) {
20025 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20026 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020027 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020028 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020029
20030 if(my $V = $TargetVersion{$LibVersion}) {
20031 $Descriptor{$LibVersion}{"Version"} = $V;
20032 }
20033 else {
20034 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20035 }
20036
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020037 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020038 if(not $SkipTypes{$LibVersion})
20039 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020040 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020041 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020042
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020043 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020044 { # if not defined by -skip-symbols option
20045 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20046 if(not $SkipSymbols{$LibVersion})
20047 { # support for old dumps
20048 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20049 }
20050 if(not $SkipSymbols{$LibVersion})
20051 { # support for old dumps
20052 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20053 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020054 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020055 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020056
20057 if(not $TargetHeaders{$LibVersion})
20058 { # if not defined by -headers-list option
20059 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20060 }
20061
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020062 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020063 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020064 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020065 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020066 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020067 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020068 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020069 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020070 if(not checkDump($LibVersion, "2.10.1")
20071 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020072 { # support for old ABI dumps: added target headers
20073 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020074 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020075 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020076 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020077 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020078 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020079 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020080 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020081 if(defined $ABI->{"GccConstants"})
20082 { # 3.0
20083 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20084 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20085 }
20086 }
20087
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020088 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020089 if(not $NestedNameSpaces{$LibVersion})
20090 { # support for old dumps
20091 # Cannot reconstruct NameSpaces. This may affect design
20092 # of the compatibility report.
20093 $NestedNameSpaces{$LibVersion} = {};
20094 }
20095 # target system type
20096 # needed to adopt HTML report
20097 if(not $DumpSystem)
20098 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020099 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020100 }
20101 # recreate environment
20102 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20103 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020104 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020105 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020106 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20107 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020108 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020109 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020110 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020111 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20112 {
20113 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20114 setLanguage($LibVersion, "C++");
20115 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020116 }
20117 }
20118 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020119 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20120 {
20121 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20122 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20123 }
20124 }
20125
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020126 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020127 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020128 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020129 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020130 {
20131 if(not $Symbol_Library{$LibVersion}{$MnglName}
20132 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20133 push(@VFunc, $MnglName);
20134 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020135 }
20136 }
20137 translateSymbols(@VFunc, $LibVersion);
20138 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020139 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20140
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020141 if(not checkDump($LibVersion, "3.0"))
20142 { # support for old ABI dumps
20143 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20144 {
20145 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20146 {
20147 if(ref($BaseType) eq "HASH") {
20148 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20149 }
20150 }
20151 }
20152 }
20153
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020154 if(not checkDump($LibVersion, "3.2"))
20155 { # support for old ABI dumps
20156 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20157 {
20158 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20159 {
20160 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20161 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20162 }
20163 }
20164 }
20165
20166 # repair target headers list
20167 delete($TargetHeaders{$LibVersion});
20168 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020169 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20170 }
20171 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20172 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020173 }
20174
20175 # non-target constants from anon enums
20176 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20177 {
20178 if(not $ExtraDump
20179 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20180 {
20181 delete($Constants{$LibVersion}{$Name});
20182 }
20183 }
20184 }
20185
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020186 if(not checkDump($LibVersion, "2.20"))
20187 { # support for old ABI dumps
20188 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20189 {
20190 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20191
20192 if($TType=~/Struct|Union|Enum|Typedef/)
20193 { # repair complex types first
20194 next;
20195 }
20196
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020197 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020198 {
20199 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20200 if($BType=~/Struct|Union|Enum/i)
20201 {
20202 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20203 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20204 }
20205 }
20206 }
20207 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20208 {
20209 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20210 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20211 if($TType=~/Struct|Union|Enum/) {
20212 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20213 }
20214 }
20215 }
20216
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020217 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020218 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020219 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20220 { # support for old ABI dumps < 2.0 (ACC 1.22)
20221 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20222 {
20223 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20224 {
20225 if($Access ne "public") {
20226 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20227 }
20228 }
20229 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20230 }
20231 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20232 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020233 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20234 { # support for old ABI dumps
20235 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20236 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020237 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20238 { # DWARF ABI Dumps
20239 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20240 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020241 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20242 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20243 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020244 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20245 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020246 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020247 foreach (keys(%{$TInfo{"Base"}})) {
20248 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020249 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020250 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020251 if($TInfo{"Type"} eq "MethodPtr")
20252 {
20253 if(defined $TInfo{"Param"})
20254 { # support for old ABI dumps <= 1.17
20255 if(not defined $TInfo{"Param"}{"0"})
20256 {
20257 my $Max = keys(%{$TInfo{"Param"}});
20258 foreach my $Pos (1 .. $Max) {
20259 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20260 }
20261 delete($TInfo{"Param"}{$Max});
20262 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20263 }
20264 }
20265 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020266 if($TInfo{"BaseType"} eq $TypeId)
20267 { # fix ABI dump
20268 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20269 }
20270 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020271 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020272 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020273 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020274 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20275 if(not $BName)
20276 { # broken type
20277 next;
20278 }
20279 if($TInfo{"Name"} eq $BName)
20280 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020281 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020282 next;
20283 }
20284 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20285 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020286 }
20287 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020288 }
20289 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20290 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020291 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020292 }
20293 }
20294
20295 if(not checkDump($LibVersion, "2.15"))
20296 { # support for old ABI dumps
20297 my %Dups = ();
20298 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20299 {
20300 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020301 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020302 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20303 { # remove template decls
20304 delete($SymbolInfo{$LibVersion}{$InfoId});
20305 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020306 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020307 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020308 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20309 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020310 { # templates
20311 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020312 }
20313 }
20314 }
20315
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020316 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20317 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020318 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20319 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20320 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20321 { # support for old ABI dumps (< 3.1)
20322 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20323 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20324 { # add "this" first parameter
20325 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20326 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20327
20328 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20329 {
20330 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20331 foreach my $Pos (reverse(0 .. $#Pos)) {
20332 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20333 }
20334 }
20335 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20336 }
20337 }
20338
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020339 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20340 { # ABI dumps have no mangled names for C-functions
20341 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20342 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020343 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20344 { # support for old ABI dumps
20345 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20346 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020347 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20348 { # DWARF ABI Dumps
20349 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20350 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020351 }
20352
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020353 $Descriptor{$LibVersion}{"Dump"} = 1;
20354}
20355
20356sub read_Machine_DumpInfo($$)
20357{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020358 my ($ABI, $LibVersion) = @_;
20359 if($ABI->{"Arch"}) {
20360 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020361 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020362 if($ABI->{"WordSize"}) {
20363 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020364 }
20365 else
20366 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020367 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020368 }
20369 if(not $WORD_SIZE{$LibVersion})
20370 { # support for old dumps (<1.23)
20371 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20372 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020373 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020374 }
20375 else
20376 {
20377 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020378 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020379 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020380 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20381 { # any "pointer"-type
20382 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020383 last;
20384 }
20385 }
20386 if($PSize)
20387 { # a pointer type size
20388 $WORD_SIZE{$LibVersion} = $PSize;
20389 }
20390 else {
20391 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20392 }
20393 }
20394 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020395 if($ABI->{"GccVersion"}) {
20396 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020397 }
20398}
20399
20400sub read_Libs_DumpInfo($$)
20401{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020402 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020403 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20404 if(not $Library_Symbol{$LibVersion})
20405 { # support for old dumps
20406 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20407 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020408 if(keys(%{$Library_Symbol{$LibVersion}})
20409 and not $DumpAPI) {
20410 $Descriptor{$LibVersion}{"Libs"} = "OK";
20411 }
20412}
20413
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020414sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020415{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020416 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020417
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020418 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020419 and not $DumpAPI) {
20420 $Descriptor{$LibVersion}{"Headers"} = "OK";
20421 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020422 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020423 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020424 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020425 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020426 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020427
20428 if(keys(%{$ABI->{"Sources"}})
20429 and not $DumpAPI) {
20430 $Descriptor{$LibVersion}{"Sources"} = "OK";
20431 }
20432 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020433 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020434 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20435 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20436 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020437}
20438
20439sub find_libs($$$)
20440{
20441 my ($Path, $Type, $MaxDepth) = @_;
20442 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020443 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020444}
20445
20446sub createDescriptor($$)
20447{
20448 my ($LibVersion, $Path) = @_;
20449 if(not $LibVersion or not $Path
20450 or not -e $Path) {
20451 return "";
20452 }
20453 if(-d $Path)
20454 { # directory with headers files and shared objects
20455 return "
20456 <version>
20457 ".$TargetVersion{$LibVersion}."
20458 </version>
20459
20460 <headers>
20461 $Path
20462 </headers>
20463
20464 <libs>
20465 $Path
20466 </libs>";
20467 }
20468 else
20469 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020470 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020471 { # standard XML-descriptor
20472 return readFile($Path);
20473 }
20474 elsif(is_header($Path, 2, $LibVersion))
20475 { # header file
20476 return "
20477 <version>
20478 ".$TargetVersion{$LibVersion}."
20479 </version>
20480
20481 <headers>
20482 $Path
20483 </headers>
20484
20485 <libs>
20486 none
20487 </libs>";
20488 }
20489 elsif(parse_libname($Path, "name", $OStarget))
20490 { # shared object
20491 return "
20492 <version>
20493 ".$TargetVersion{$LibVersion}."
20494 </version>
20495
20496 <headers>
20497 none
20498 </headers>
20499
20500 <libs>
20501 $Path
20502 </libs>";
20503 }
20504 else
20505 { # standard XML-descriptor
20506 return readFile($Path);
20507 }
20508 }
20509}
20510
20511sub detect_lib_default_paths()
20512{
20513 my %LPaths = ();
20514 if($OSgroup eq "bsd")
20515 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020516 if(my $LdConfig = get_CmdPath("ldconfig"))
20517 {
20518 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20519 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020520 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20521 {
20522 my $Name = "lib".$1;
20523 if(not defined $LPaths{$Name}) {
20524 $LPaths{$Name} = $2;
20525 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020526 }
20527 }
20528 }
20529 else {
20530 printMsg("WARNING", "can't find ldconfig");
20531 }
20532 }
20533 else
20534 {
20535 if(my $LdConfig = get_CmdPath("ldconfig"))
20536 {
20537 if($SystemRoot and $OSgroup eq "linux")
20538 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20539 if(-e $SystemRoot."/etc/ld.so.conf") {
20540 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20541 }
20542 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020543 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20544 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020545 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20546 {
20547 my ($Name, $Path) = ($1, $2);
20548 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020549 if(not defined $LPaths{$Name})
20550 { # get first element from the list of available paths
20551
20552 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20553 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20554 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20555
20556 $LPaths{$Name} = $Path;
20557 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020558 }
20559 }
20560 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020561 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020562 printMsg("WARNING", "can't find ldconfig");
20563 }
20564 }
20565 return \%LPaths;
20566}
20567
20568sub detect_bin_default_paths()
20569{
20570 my $EnvPaths = $ENV{"PATH"};
20571 if($OSgroup eq "beos") {
20572 $EnvPaths.=":".$ENV{"BETOOLS"};
20573 }
20574 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020575 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020576 {
20577 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020578 next if(not $Path);
20579 if($SystemRoot
20580 and $Path=~/\A\Q$SystemRoot\E\//)
20581 { # do NOT use binaries from target system
20582 next;
20583 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020584 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020585 }
20586}
20587
20588sub detect_inc_default_paths()
20589{
20590 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020591 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020592 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020593 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020594 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020595 next if(index($Line, "/cc1plus ")!=-1);
20596
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020597 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20598 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020599 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020600 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020601 if(index($Path, "c++")!=-1
20602 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020603 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020604 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020605 if(not defined $MAIN_CPP_DIR
20606 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20607 $MAIN_CPP_DIR = $Path;
20608 }
20609 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020610 elsif(index($Path, "gcc")!=-1) {
20611 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020612 }
20613 else
20614 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020615 if($Path=~/local[\/\\]+include/)
20616 { # local paths
20617 next;
20618 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020619 if($SystemRoot
20620 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20621 { # The GCC include path for user headers is not a part of the system root
20622 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20623 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20624 next;
20625 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020626 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020627 }
20628 }
20629 }
20630 unlink("$TMP_DIR/empty.h");
20631 return %DPaths;
20632}
20633
20634sub detect_default_paths($)
20635{
20636 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20637 my $Search = $_[0];
20638 if($Search!~/inc/) {
20639 $HSearch = 0;
20640 }
20641 if($Search!~/lib/) {
20642 $LSearch = 0;
20643 }
20644 if($Search!~/bin/) {
20645 $BSearch = 0;
20646 }
20647 if($Search!~/gcc/) {
20648 $GSearch = 0;
20649 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020650 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020651 { # <search_headers> section of the XML descriptor
20652 # do NOT search for systems headers
20653 $HSearch = 0;
20654 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020655 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020656 { # <search_libs> section of the XML descriptor
20657 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020658 $LSearch = 0;
20659 }
20660 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20661 { # additional search paths
20662 next if($Type eq "include" and not $HSearch);
20663 next if($Type eq "lib" and not $LSearch);
20664 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020665 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020666 }
20667 if($OSgroup ne "windows")
20668 { # unix-like
20669 foreach my $Type ("include", "lib", "bin")
20670 { # automatic detection of system "devel" directories
20671 next if($Type eq "include" and not $HSearch);
20672 next if($Type eq "lib" and not $LSearch);
20673 next if($Type eq "bin" and not $BSearch);
20674 my ($UsrDir, $RootDir) = ("/usr", "/");
20675 if($SystemRoot and $Type ne "bin")
20676 { # 1. search for target headers and libraries
20677 # 2. use host commands: ldconfig, readelf, etc.
20678 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20679 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020680 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020681 if(-d $RootDir."/".$Type)
20682 { # if "/lib" is symbolic link
20683 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020684 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020685 }
20686 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020687 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020688 }
20689 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020690 if(-d $UsrDir)
20691 {
20692 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020693 if(-d $UsrDir."/".$Type)
20694 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020695 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020696 }
20697 }
20698 }
20699 }
20700 if($BSearch)
20701 {
20702 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020703 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020704 }
20705 # check environment variables
20706 if($OSgroup eq "beos")
20707 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020708 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020709 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020710 if($_ eq ".") {
20711 next;
20712 }
20713 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20714 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20715 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020716 }
20717 }
20718 if($HSearch)
20719 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020720 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20721 split(/:|;/, $ENV{"BEINCLUDES"})
20722 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020723 }
20724 if($LSearch)
20725 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020726 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20727 split(/:|;/, $ENV{"BELIBRARIES"}),
20728 split(/:|;/, $ENV{"LIBRARY_PATH"})
20729 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020730 }
20731 }
20732 if($LSearch)
20733 { # using linker to get system paths
20734 if(my $LPaths = detect_lib_default_paths())
20735 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020736 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020737 foreach my $Name (keys(%{$LPaths}))
20738 {
20739 if($SystemRoot
20740 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20741 { # wrong ldconfig configuration
20742 # check your <sysroot>/etc/ld.so.conf
20743 next;
20744 }
20745 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020746 if(my $Dir = get_dirname($LPaths->{$Name})) {
20747 $Dirs{$Dir} = 1;
20748 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020749 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020750 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020751 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020752 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020753 }
20754 if($BSearch)
20755 {
20756 if($CrossGcc)
20757 { # --cross-gcc=arm-linux-gcc
20758 if(-e $CrossGcc)
20759 { # absolute or relative path
20760 $GCC_PATH = get_abs_path($CrossGcc);
20761 }
20762 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20763 { # command name
20764 $GCC_PATH = $CrossGcc;
20765 }
20766 else {
20767 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20768 }
20769 if($GCC_PATH=~/\s/) {
20770 $GCC_PATH = "\"".$GCC_PATH."\"";
20771 }
20772 }
20773 }
20774 if($GSearch)
20775 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020776 if(not $CrossGcc)
20777 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020778 $GCC_PATH = get_CmdPath("gcc");
20779 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020780 if(not $GCC_PATH)
20781 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020782 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020783 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020784 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020785 { # select the latest version
20786 @GCCs = sort {$b cmp $a} @GCCs;
20787 if(check_gcc($GCCs[0], "3"))
20788 {
20789 $GCC_PATH = $GCCs[0];
20790 last;
20791 }
20792 }
20793 }
20794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020795 if(not $GCC_PATH) {
20796 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20797 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020798
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020799 if(not $CheckObjectsOnly_Opt)
20800 {
20801 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
20802 {
20803 my $GccTarget = get_dumpmachine($GCC_PATH);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020804 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020805
20806 if($GccTarget=~/linux/)
20807 {
20808 $OStarget = "linux";
20809 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20810 }
20811 elsif($GccTarget=~/symbian/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020812 {
20813 $OStarget = "symbian";
20814 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20815 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020816
20817 # check GCC version
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020818 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020819 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040020820 # introduced in 4.8
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020821 # fixed in 4.8.3
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020822 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20823 $EMERGENCY_MODE_48 = 1;
20824 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020825 }
20826 else {
20827 exitStatus("Error", "something is going wrong with the GCC compiler");
20828 }
20829 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020830 if($HSearch)
20831 {
20832 if(not $NoStdInc)
20833 { # do NOT search in GCC standard paths
20834 my %DPaths = detect_inc_default_paths();
20835 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20836 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20837 @DefaultIncPaths = @{$DPaths{"Inc"}};
20838 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020839 }
20840 }
20841 }
20842 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020843 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020844 my $IncPath = "/usr/include";
20845 if($SystemRoot) {
20846 $IncPath = $SystemRoot.$IncPath;
20847 }
20848 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020849 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020850 }
20851 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020852
20853 if($ExtraInfo)
20854 {
20855 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20856 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20857 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020858}
20859
20860sub getLIB_EXT($)
20861{
20862 my $Target = $_[0];
20863 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20864 return $Ext;
20865 }
20866 return $OS_LibExt{$LIB_TYPE}{"default"};
20867}
20868
20869sub getAR_EXT($)
20870{
20871 my $Target = $_[0];
20872 if(my $Ext = $OS_Archive{$Target}) {
20873 return $Ext;
20874 }
20875 return $OS_Archive{"default"};
20876}
20877
20878sub get_dumpversion($)
20879{
20880 my $Cmd = $_[0];
20881 return "" if(not $Cmd);
20882 if($Cache{"get_dumpversion"}{$Cmd}) {
20883 return $Cache{"get_dumpversion"}{$Cmd};
20884 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020885 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020886 chomp($V);
20887 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20888}
20889
20890sub get_dumpmachine($)
20891{
20892 my $Cmd = $_[0];
20893 return "" if(not $Cmd);
20894 if($Cache{"get_dumpmachine"}{$Cmd}) {
20895 return $Cache{"get_dumpmachine"}{$Cmd};
20896 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020897 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020898 chomp($Machine);
20899 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20900}
20901
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020902sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020903{
20904 my $Cmd = $_[0];
20905 return "" if(not $Cmd);
20906 my @Options = (
20907 "--version",
20908 "-help"
20909 );
20910 foreach my $Opt (@Options)
20911 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020912 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020913 if($Info) {
20914 return 1;
20915 }
20916 }
20917 return 0;
20918}
20919
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020920sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020921{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020922 my ($Cmd, $ReqVer) = @_;
20923 return 0 if(not $Cmd or not $ReqVer);
20924 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20925 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020926 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020927 if(my $GccVer = get_dumpversion($Cmd))
20928 {
20929 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20930 if(cmpVersions($GccVer, $ReqVer)>=0) {
20931 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20932 }
20933 }
20934 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020935}
20936
20937sub get_depth($)
20938{
20939 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020940 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020941 }
20942 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20943}
20944
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020945sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020946{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020947 return if($Cache{"registerGccHeaders"}); # this function should be called once
20948
20949 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020950 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020951 my @Headers = cmd_find($Path,"f");
20952 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20953 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020954 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020955 my $FileName = get_filename($HPath);
20956 if(not defined $DefaultGccHeader{$FileName})
20957 { # skip duplicated
20958 $DefaultGccHeader{$FileName} = $HPath;
20959 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020960 }
20961 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020962 $Cache{"registerGccHeaders"} = 1;
20963}
20964
20965sub registerCppHeaders()
20966{
20967 return if($Cache{"registerCppHeaders"}); # this function should be called once
20968
20969 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020970 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020971 my @Headers = cmd_find($CppDir,"f");
20972 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20973 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020974 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020975 my $FileName = get_filename($Path);
20976 if(not defined $DefaultCppHeader{$FileName})
20977 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020978 $DefaultCppHeader{$FileName} = $Path;
20979 }
20980 }
20981 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020982 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020983}
20984
20985sub parse_libname($$$)
20986{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020987 return "" if(not $_[0]);
20988 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20989 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020990 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020991 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20992}
20993
20994sub parse_libname_I($$$)
20995{
20996 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020997
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020998 if($Target eq "symbian") {
20999 return parse_libname_symbian($Name, $Type);
21000 }
21001 elsif($Target eq "windows") {
21002 return parse_libname_windows($Name, $Type);
21003 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021004
21005 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021006 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021007 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021008 { # libSDL-1.2.so.0.7.1
21009 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021010 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021011 if($Type eq "name")
21012 { # libSDL-1.2
21013 # libwbxml2
21014 return $2;
21015 }
21016 elsif($Type eq "name+ext")
21017 { # libSDL-1.2.so
21018 # libwbxml2.so
21019 return $1;
21020 }
21021 elsif($Type eq "version")
21022 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021023 if(defined $7
21024 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021025 { # 0.7.1
21026 return $7;
21027 }
21028 else
21029 { # libc-2.5.so (=>2.5 version)
21030 my $MV = $5;
21031 $MV=~s/\A[\-\_]+//g;
21032 return $MV;
21033 }
21034 }
21035 elsif($Type eq "short")
21036 { # libSDL
21037 # libwbxml2
21038 return $3;
21039 }
21040 elsif($Type eq "shortest")
21041 { # SDL
21042 # wbxml
21043 return shortest_name($3);
21044 }
21045 }
21046 return "";# error
21047}
21048
21049sub parse_libname_symbian($$)
21050{
21051 my ($Name, $Type) = @_;
21052 my $Ext = getLIB_EXT("symbian");
21053 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21054 { # libpthread{00010001}.dso
21055 if($Type eq "name")
21056 { # libpthread{00010001}
21057 return $2;
21058 }
21059 elsif($Type eq "name+ext")
21060 { # libpthread{00010001}.dso
21061 return $1;
21062 }
21063 elsif($Type eq "version")
21064 { # 00010001
21065 my $V = $4;
21066 $V=~s/\{(.+)\}/$1/;
21067 return $V;
21068 }
21069 elsif($Type eq "short")
21070 { # libpthread
21071 return $3;
21072 }
21073 elsif($Type eq "shortest")
21074 { # pthread
21075 return shortest_name($3);
21076 }
21077 }
21078 return "";# error
21079}
21080
21081sub parse_libname_windows($$)
21082{
21083 my ($Name, $Type) = @_;
21084 my $Ext = getLIB_EXT("windows");
21085 if($Name=~/((.+?)\.$Ext)\Z/)
21086 { # netapi32.dll
21087 if($Type eq "name")
21088 { # netapi32
21089 return $2;
21090 }
21091 elsif($Type eq "name+ext")
21092 { # netapi32.dll
21093 return $1;
21094 }
21095 elsif($Type eq "version")
21096 { # DLL version embedded
21097 # at binary-level
21098 return "";
21099 }
21100 elsif($Type eq "short")
21101 { # netapi32
21102 return $2;
21103 }
21104 elsif($Type eq "shortest")
21105 { # netapi
21106 return shortest_name($2);
21107 }
21108 }
21109 return "";# error
21110}
21111
21112sub shortest_name($)
21113{
21114 my $Name = $_[0];
21115 # remove prefix
21116 $Name=~s/\A(lib|open)//;
21117 # remove suffix
21118 $Name=~s/[\W\d_]+\Z//i;
21119 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21120 return $Name;
21121}
21122
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021123sub createSymbolsList($$$$$)
21124{
21125 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
21126 read_ABI_Dump(1, $DPath);
21127 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021128 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021129 }
21130 my %SymbolHeaderLib = ();
21131 my $Total = 0;
21132 # Get List
21133 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21134 {
21135 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021136 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021137 next;
21138 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021139 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021140 { # skip other symbols
21141 next;
21142 }
21143 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21144 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021145 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021146 next;
21147 }
21148 my $DyLib = $Symbol_Library{1}{$Symbol};
21149 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021150 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021151 next;
21152 }
21153 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21154 $Total+=1;
21155 }
21156 # Draw List
21157 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21158 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21159 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21160 {
21161 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21162 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021163 my %NS_Symbol = ();
21164 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021165 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021166 }
21167 foreach my $NameSpace (sort keys(%NS_Symbol))
21168 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021169 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021170 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21171 foreach my $Symbol (@SortedInterfaces)
21172 {
21173 my $SubReport = "";
21174 my $Signature = get_Signature($Symbol, 1);
21175 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021176 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021177 }
21178 if($Symbol=~/\A(_Z|\?)/)
21179 {
21180 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021181 $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 +040021182 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021183 else {
21184 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21185 }
21186 }
21187 else
21188 {
21189 if($Signature) {
21190 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21191 }
21192 else {
21193 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21194 }
21195 }
21196 $SYMBOLS_LIST .= $SubReport;
21197 }
21198 }
21199 $SYMBOLS_LIST .= "<br/>\n";
21200 }
21201 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021202 # clear info
21203 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21204 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21205 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21206 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021207 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021208 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021209 my $CssStyles = readModule("Styles", "SymbolsList.css");
21210 my $JScripts = readModule("Scripts", "Sections.js");
21211 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021212 my $Title = "$LName: public symbols";
21213 my $Keywords = "$LName, API, symbols";
21214 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021215 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021216 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030021217 <br/><br/><hr/>\n".getReportFooter("Single")."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021218 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021219 writeFile($SaveTo, $SYMBOLS_LIST);
21220}
21221
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021222sub add_target_libs($)
21223{
21224 foreach (@{$_[0]}) {
21225 $TargetLibs{$_} = 1;
21226 }
21227}
21228
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021229sub is_target_lib($)
21230{
21231 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021232 if(not $LName) {
21233 return 0;
21234 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021235 if($TargetLibraryName
21236 and $LName!~/\Q$TargetLibraryName\E/) {
21237 return 0;
21238 }
21239 if(keys(%TargetLibs)
21240 and not $TargetLibs{$LName}
21241 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21242 return 0;
21243 }
21244 return 1;
21245}
21246
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021247sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021248{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021249 my ($H, $V) = @_;
21250 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021251 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021252 if($TargetHeaders{$V}{$H}) {
21253 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021254 }
21255 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021256 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021257}
21258
21259sub checkVersionNum($$)
21260{
21261 my ($LibVersion, $Path) = @_;
21262 if(my $VerNum = $TargetVersion{$LibVersion}) {
21263 return $VerNum;
21264 }
21265 my $UsedAltDescr = 0;
21266 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021267 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021268 next if(isDump($Part)); # ABI dump
21269 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021270 my $VerNum = "";
21271 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021272 {
21273 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021274 $VerNum = parse_libname($Part, "version", $OStarget);
21275 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021276 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021277 }
21278 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021279 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
21280 {
21281 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021282 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021283 }
21284 if($VerNum ne "")
21285 {
21286 $TargetVersion{$LibVersion} = $VerNum;
21287 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021288 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021289 }
21290 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021291 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 +040021292 }
21293 return $TargetVersion{$LibVersion};
21294 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021295 }
21296 if($UsedAltDescr)
21297 {
21298 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021299 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021300 }
21301 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021302 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021303 }
21304 }
21305}
21306
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021307sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021308{
21309 my $Str = $_[0];
21310 return "" if(not $Str);
21311 $Str=~s/\Q$TargetLibraryName\E//g;
21312 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021313 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021314 return $2;
21315 }
21316 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
21317 return $V;
21318 }
21319 return "";
21320}
21321
21322sub readLibs($)
21323{
21324 my $LibVersion = $_[0];
21325 if($OStarget eq "windows")
21326 { # dumpbin.exe will crash
21327 # without VS Environment
21328 check_win32_env();
21329 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021330 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021331 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021332 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021333}
21334
21335sub dump_sorting($)
21336{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021337 my $Hash = $_[0];
21338 return [] if(not $Hash);
21339 my @Keys = keys(%{$Hash});
21340 return [] if($#Keys<0);
21341 if($Keys[0]=~/\A\d+\Z/)
21342 { # numbers
21343 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021344 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021345 else
21346 { # strings
21347 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021348 }
21349}
21350
21351sub printMsg($$)
21352{
21353 my ($Type, $Msg) = @_;
21354 if($Type!~/\AINFO/) {
21355 $Msg = $Type.": ".$Msg;
21356 }
21357 if($Type!~/_C\Z/) {
21358 $Msg .= "\n";
21359 }
21360 if($Quiet)
21361 { # --quiet option
21362 appendFile($COMMON_LOG_PATH, $Msg);
21363 }
21364 else
21365 {
21366 if($Type eq "ERROR") {
21367 print STDERR $Msg;
21368 }
21369 else {
21370 print $Msg;
21371 }
21372 }
21373}
21374
21375sub exitStatus($$)
21376{
21377 my ($Code, $Msg) = @_;
21378 printMsg("ERROR", $Msg);
21379 exit($ERROR_CODE{$Code});
21380}
21381
21382sub exitReport()
21383{ # the tool has run without any errors
21384 printReport();
21385 if($COMPILE_ERRORS)
21386 { # errors in headers may add false positives/negatives
21387 exit($ERROR_CODE{"Compile_Error"});
21388 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021389 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21390 { # --binary
21391 exit($ERROR_CODE{"Incompatible"});
21392 }
21393 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21394 { # --source
21395 exit($ERROR_CODE{"Incompatible"});
21396 }
21397 elsif($RESULT{"Source"}{"Problems"}
21398 or $RESULT{"Binary"}{"Problems"})
21399 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021400 exit($ERROR_CODE{"Incompatible"});
21401 }
21402 else {
21403 exit($ERROR_CODE{"Compatible"});
21404 }
21405}
21406
21407sub readRules($)
21408{
21409 my $Kind = $_[0];
21410 if(not -f $RULES_PATH{$Kind}) {
21411 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21412 }
21413 my $Content = readFile($RULES_PATH{$Kind});
21414 while(my $Rule = parseTag(\$Content, "rule"))
21415 {
21416 my $RId = parseTag(\$Rule, "id");
21417 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21418 foreach my $Prop (@Properties) {
21419 if(my $Value = parseTag(\$Rule, lc($Prop)))
21420 {
21421 $Value=~s/\n[ ]*//;
21422 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21423 }
21424 }
21425 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21426 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21427 }
21428 else {
21429 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21430 }
21431 }
21432}
21433
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021434sub getReportPath($)
21435{
21436 my $Level = $_[0];
21437 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21438 if($Level eq "Binary")
21439 {
21440 if($BinaryReportPath)
21441 { # --bin-report-path
21442 return $BinaryReportPath;
21443 }
21444 elsif($OutputReportPath)
21445 { # --report-path
21446 return $OutputReportPath;
21447 }
21448 else
21449 { # default
21450 return $Dir."/abi_compat_report.$ReportFormat";
21451 }
21452 }
21453 elsif($Level eq "Source")
21454 {
21455 if($SourceReportPath)
21456 { # --src-report-path
21457 return $SourceReportPath;
21458 }
21459 elsif($OutputReportPath)
21460 { # --report-path
21461 return $OutputReportPath;
21462 }
21463 else
21464 { # default
21465 return $Dir."/src_compat_report.$ReportFormat";
21466 }
21467 }
21468 else
21469 {
21470 if($OutputReportPath)
21471 { # --report-path
21472 return $OutputReportPath;
21473 }
21474 else
21475 { # default
21476 return $Dir."/compat_report.$ReportFormat";
21477 }
21478 }
21479}
21480
21481sub printStatMsg($)
21482{
21483 my $Level = $_[0];
21484 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21485}
21486
21487sub listAffected($)
21488{
21489 my $Level = $_[0];
21490 my $List = "";
21491 foreach (keys(%{$TotalAffected{$Level}}))
21492 {
21493 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21494 { # skip "Low"-severity problems
21495 next;
21496 }
21497 $List .= "$_\n";
21498 }
21499 my $Dir = get_dirname(getReportPath($Level));
21500 if($Level eq "Binary") {
21501 writeFile($Dir."/abi_affected.txt", $List);
21502 }
21503 elsif($Level eq "Source") {
21504 writeFile($Dir."/src_affected.txt", $List);
21505 }
21506}
21507
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021508sub printReport()
21509{
21510 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021511 createReport();
21512 if($JoinReport or $DoubleReport)
21513 {
21514 if($RESULT{"Binary"}{"Problems"}
21515 or $RESULT{"Source"}{"Problems"}) {
21516 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021517 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021518 else {
21519 printMsg("INFO", "result: COMPATIBLE");
21520 }
21521 printStatMsg("Binary");
21522 printStatMsg("Source");
21523 if($ListAffected)
21524 { # --list-affected
21525 listAffected("Binary");
21526 listAffected("Source");
21527 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021528 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021529 elsif($BinaryOnly)
21530 {
21531 if($RESULT{"Binary"}{"Problems"}) {
21532 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21533 }
21534 else {
21535 printMsg("INFO", "result: COMPATIBLE");
21536 }
21537 printStatMsg("Binary");
21538 if($ListAffected)
21539 { # --list-affected
21540 listAffected("Binary");
21541 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021542 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021543 elsif($SourceOnly)
21544 {
21545 if($RESULT{"Source"}{"Problems"}) {
21546 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21547 }
21548 else {
21549 printMsg("INFO", "result: COMPATIBLE");
21550 }
21551 printStatMsg("Source");
21552 if($ListAffected)
21553 { # --list-affected
21554 listAffected("Source");
21555 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021556 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021557 if($StdOut)
21558 {
21559 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021560 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021561 printMsg("INFO", "compatibility report has been generated to stdout");
21562 }
21563 else
21564 { # default
21565 printMsg("INFO", "compatibility reports have been generated to stdout");
21566 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021567 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021568 else
21569 {
21570 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021571 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021572 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21573 }
21574 elsif($DoubleReport)
21575 { # default
21576 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21577 }
21578 elsif($BinaryOnly)
21579 { # --binary
21580 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21581 }
21582 elsif($SourceOnly)
21583 { # --source
21584 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21585 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021586 }
21587}
21588
21589sub check_win32_env()
21590{
21591 if(not $ENV{"DevEnvDir"}
21592 or not $ENV{"LIB"}) {
21593 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21594 }
21595}
21596
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021597sub diffSets($$)
21598{
21599 my ($S1, $S2) = @_;
21600 my @SK1 = keys(%{$S1});
21601 my @SK2 = keys(%{$S2});
21602 if($#SK1!=$#SK2) {
21603 return 1;
21604 }
21605 foreach my $K1 (@SK1)
21606 {
21607 if(not defined $S2->{$K1}) {
21608 return 1;
21609 }
21610 }
21611 return 0;
21612}
21613
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021614sub defaultDumpPath($$)
21615{
21616 my ($N, $V) = @_;
21617 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21618}
21619
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021620sub create_ABI_Dump()
21621{
21622 if(not -e $DumpAPI) {
21623 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21624 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021625
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021626 my @DParts = split(/\s*,\s*/, $DumpAPI);
21627 foreach my $Part (@DParts)
21628 {
21629 if(not -e $Part) {
21630 exitStatus("Access_Error", "can't access \'$Part\'");
21631 }
21632 }
21633 checkVersionNum(1, $DumpAPI);
21634 foreach my $Part (@DParts)
21635 {
21636 if(isDump($Part)) {
21637 read_ABI_Dump(1, $Part);
21638 }
21639 else {
21640 readDescriptor(1, createDescriptor(1, $Part));
21641 }
21642 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021643
21644 if(not $Descriptor{1}{"Version"})
21645 { # set to default: X
21646 $Descriptor{1}{"Version"} = "X";
21647 }
21648
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021649 initLogging(1);
21650 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021651
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021652 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021653 if($OutputDumpPath)
21654 { # user defined path
21655 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021656 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021657 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21658
21659 if(not $Archive and not $StdOut)
21660 { # check archive utilities
21661 if($OSgroup eq "windows")
21662 { # using zip
21663 my $ZipCmd = get_CmdPath("zip");
21664 if(not $ZipCmd) {
21665 exitStatus("Not_Found", "can't find \"zip\"");
21666 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021667 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021668 else
21669 { # using tar and gzip
21670 my $TarCmd = get_CmdPath("tar");
21671 if(not $TarCmd) {
21672 exitStatus("Not_Found", "can't find \"tar\"");
21673 }
21674 my $GzipCmd = get_CmdPath("gzip");
21675 if(not $GzipCmd) {
21676 exitStatus("Not_Found", "can't find \"gzip\"");
21677 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021678 }
21679 }
21680
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021681 if(not $Descriptor{1}{"Dump"})
21682 {
21683 if(not $CheckHeadersOnly) {
21684 readLibs(1);
21685 }
21686 if($CheckHeadersOnly) {
21687 setLanguage(1, "C++");
21688 }
21689 if(not $CheckObjectsOnly) {
21690 searchForHeaders(1);
21691 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021692 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021693 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021694 if(not $Descriptor{1}{"Dump"})
21695 {
21696 if($Descriptor{1}{"Headers"}) {
21697 readHeaders(1);
21698 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021699 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021700 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021701 if(not keys(%{$SymbolInfo{1}}))
21702 { # check if created dump is valid
21703 if(not $ExtendedCheck and not $CheckObjectsOnly)
21704 {
21705 if($CheckHeadersOnly) {
21706 exitStatus("Empty_Set", "the set of public symbols is empty");
21707 }
21708 else {
21709 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21710 }
21711 }
21712 }
21713 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021714 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021715 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21716 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021717 if($ExtraDump)
21718 { # add unmangled names to the ABI dump
21719 my @Names = ();
21720 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21721 {
21722 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21723 push(@Names, $MnglName);
21724 }
21725 }
21726 translateSymbols(@Names, 1);
21727 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21728 {
21729 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21730 {
21731 if(my $Unmangled = $tr_name{$MnglName})
21732 {
21733 if($MnglName ne $Unmangled) {
21734 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21735 }
21736 }
21737 }
21738 }
21739 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021740
21741 my %GccConstants = (); # built-in GCC constants
21742 foreach my $Name (keys(%{$Constants{1}}))
21743 {
21744 if(not defined $Constants{1}{$Name}{"Header"})
21745 {
21746 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21747 delete($Constants{1}{$Name});
21748 }
21749 }
21750
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021751 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021752 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021753 "TypeInfo" => $TypeInfo{1},
21754 "SymbolInfo" => $SymbolInfo{1},
21755 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021756 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021757 "SymbolVersion" => $SymVer{1},
21758 "LibraryVersion" => $Descriptor{1}{"Version"},
21759 "LibraryName" => $TargetLibraryName,
21760 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021761 "SkipTypes" => $SkipTypes{1},
21762 "SkipSymbols" => $SkipSymbols{1},
21763 "SkipNameSpaces" => $SkipNameSpaces{1},
21764 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021765 "Headers" => \%HeadersInfo,
21766 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021767 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021768 "NameSpaces" => $NestedNameSpaces{1},
21769 "Target" => $OStarget,
21770 "Arch" => getArch(1),
21771 "WordSize" => $WORD_SIZE{1},
21772 "GccVersion" => get_dumpversion($GCC_PATH),
21773 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21774 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21775 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021776 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021777 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021778 }
21779 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021780 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021781 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021782 if($ExtendedCheck)
21783 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021784 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021785 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021786 if($BinaryOnly)
21787 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021788 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021789 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021790 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021791 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021792 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021793 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21794 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021795 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021796
21797 my $ABI_DUMP = "";
21798 if($UseXML)
21799 {
21800 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021801 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021802 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021803 else
21804 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021805 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021806 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021807 if($StdOut)
21808 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021809 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021810 printMsg("INFO", "ABI dump has been generated to stdout");
21811 return;
21812 }
21813 else
21814 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021815 my ($DDir, $DName) = separate_path($DumpPath);
21816 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021817 if(not $Archive) {
21818 $DPath = $DumpPath;
21819 }
21820
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021821 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021822
21823 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021824 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021825 close(DUMP);
21826
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021827 if(not -s $DPath) {
21828 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21829 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021830 if($Archive) {
21831 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021832 }
21833
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021834 if($OutputDumpPath) {
21835 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021836 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021837 else {
21838 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21839 }
21840 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 +040021841 }
21842}
21843
21844sub quickEmptyReports()
21845{ # Quick "empty" reports
21846 # 4 times faster than merging equal dumps
21847 # NOTE: the dump contains the "LibraryVersion" attribute
21848 # if you change the version, then your dump will be different
21849 # OVERCOME: use -v1 and v2 options for comparing dumps
21850 # and don't change version in the XML descriptor (and dumps)
21851 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21852 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21853 {
21854 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21855 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21856 if($FilePath1 and $FilePath2)
21857 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021858 my $Line = readLineNum($FilePath1, 0);
21859 if($Line=~/xml/)
21860 { # XML format
21861 # is not supported yet
21862 return;
21863 }
21864
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021865 local $/ = undef;
21866
21867 open(DUMP1, $FilePath1);
21868 my $Content1 = <DUMP1>;
21869 close(DUMP1);
21870
21871 open(DUMP2, $FilePath2);
21872 my $Content2 = <DUMP2>;
21873 close(DUMP2);
21874
21875 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021876 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021877 # clean memory
21878 undef $Content2;
21879
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021880 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021881 my $ABIdump = eval($Content1);
21882
21883 # clean memory
21884 undef $Content1;
21885
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021886 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021887 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 +040021888 }
21889 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021890 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021891 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21892 }
21893 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021894 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021895 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21896 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021897 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021898 read_Libs_DumpInfo($ABIdump, 1);
21899 read_Machine_DumpInfo($ABIdump, 1);
21900 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021901
21902 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21903 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21904
21905 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21906 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21907
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021908 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21909 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21910 exitReport();
21911 }
21912 }
21913 }
21914}
21915
21916sub initLogging($)
21917{
21918 my $LibVersion = $_[0];
21919 # create log directory
21920 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21921 if($OutputLogPath{$LibVersion})
21922 { # user-defined by -log-path option
21923 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21924 }
21925 if($LogMode ne "n") {
21926 mkpath($LOG_DIR);
21927 }
21928 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021929 if($Debug)
21930 { # debug directory
21931 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021932
21933 if(not $ExtraInfo)
21934 { # enable --extra-info
21935 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21936 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021937 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021938 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021939}
21940
21941sub writeLog($$)
21942{
21943 my ($LibVersion, $Msg) = @_;
21944 if($LogMode ne "n") {
21945 appendFile($LOG_PATH{$LibVersion}, $Msg);
21946 }
21947}
21948
21949sub resetLogging($)
21950{
21951 my $LibVersion = $_[0];
21952 if($LogMode!~/a|n/)
21953 { # remove old log
21954 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021955 if($Debug) {
21956 rmtree($DEBUG_PATH{$LibVersion});
21957 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021958 }
21959}
21960
21961sub printErrorLog($)
21962{
21963 my $LibVersion = $_[0];
21964 if($LogMode ne "n") {
21965 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21966 }
21967}
21968
21969sub isDump($)
21970{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021971 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
21972 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021973 return $1;
21974 }
21975 return 0;
21976}
21977
21978sub isDump_U($)
21979{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021980 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021981 return $1;
21982 }
21983 return 0;
21984}
21985
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021986sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021987{
21988 # read input XML descriptors or ABI dumps
21989 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021990 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021991 }
21992 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
21993 foreach my $Part (@DParts1)
21994 {
21995 if(not -e $Part) {
21996 exitStatus("Access_Error", "can't access \'$Part\'");
21997 }
21998 }
21999 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022000 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022001 }
22002 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
22003 foreach my $Part (@DParts2)
22004 {
22005 if(not -e $Part) {
22006 exitStatus("Access_Error", "can't access \'$Part\'");
22007 }
22008 }
22009 detect_default_paths("bin"); # to extract dumps
22010 if($#DParts1==0 and $#DParts2==0
22011 and isDump($Descriptor{1}{"Path"})
22012 and isDump($Descriptor{2}{"Path"}))
22013 { # optimization: equal ABI dumps
22014 quickEmptyReports();
22015 }
22016 checkVersionNum(1, $Descriptor{1}{"Path"});
22017 checkVersionNum(2, $Descriptor{2}{"Path"});
22018 printMsg("INFO", "preparation, please wait ...");
22019 foreach my $Part (@DParts1)
22020 {
22021 if(isDump($Part)) {
22022 read_ABI_Dump(1, $Part);
22023 }
22024 else {
22025 readDescriptor(1, createDescriptor(1, $Part));
22026 }
22027 }
22028 foreach my $Part (@DParts2)
22029 {
22030 if(isDump($Part)) {
22031 read_ABI_Dump(2, $Part);
22032 }
22033 else {
22034 readDescriptor(2, createDescriptor(2, $Part));
22035 }
22036 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022037
22038 if(not $Descriptor{1}{"Version"})
22039 { # set to default: X
22040 $Descriptor{1}{"Version"} = "X";
22041 }
22042
22043 if(not $Descriptor{2}{"Version"})
22044 { # set to default: Y
22045 $Descriptor{2}{"Version"} = "Y";
22046 }
22047
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022048 initLogging(1);
22049 initLogging(2);
22050 # check consistency
22051 if(not $Descriptor{1}{"Headers"}
22052 and not $Descriptor{1}{"Libs"}) {
22053 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
22054 }
22055 if(not $Descriptor{2}{"Headers"}
22056 and not $Descriptor{2}{"Libs"}) {
22057 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
22058 }
22059 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
22060 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
22061 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
22062 }
22063 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
22064 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
22065 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
22066 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022067 if(not $Descriptor{1}{"Headers"})
22068 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022069 if($CheckHeadersOnly_Opt) {
22070 exitStatus("Error", "can't find header files info in descriptor d1");
22071 }
22072 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022073 if(not $Descriptor{2}{"Headers"})
22074 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022075 if($CheckHeadersOnly_Opt) {
22076 exitStatus("Error", "can't find header files info in descriptor d2");
22077 }
22078 }
22079 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022080 or not $Descriptor{2}{"Headers"})
22081 {
22082 if(not $CheckObjectsOnly_Opt)
22083 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022084 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
22085 $CheckObjectsOnly = 1;
22086 }
22087 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022088 if(not $Descriptor{1}{"Libs"})
22089 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022090 if($CheckObjectsOnly_Opt) {
22091 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
22092 }
22093 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022094 if(not $Descriptor{2}{"Libs"})
22095 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022096 if($CheckObjectsOnly_Opt) {
22097 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
22098 }
22099 }
22100 if(not $Descriptor{1}{"Libs"}
22101 or not $Descriptor{2}{"Libs"})
22102 { # comparing standalone header files
22103 # comparing ABI dumps created with --headers-only
22104 if(not $CheckHeadersOnly_Opt)
22105 {
22106 printMsg("WARNING", "checking headers only");
22107 $CheckHeadersOnly = 1;
22108 }
22109 }
22110 if($UseDumps)
22111 { # --use-dumps
22112 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022113 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22114 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022115
22116 unlink($DumpPath1);
22117 unlink($DumpPath2);
22118
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022119 my $pid = fork();
22120 if($pid)
22121 { # dump on two CPU cores
22122 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22123 if($RelativeDirectory{1}) {
22124 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22125 }
22126 if($OutputLogPath{1}) {
22127 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22128 }
22129 if($CrossGcc) {
22130 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22131 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022132 if($Quiet)
22133 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022134 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022135 @PARAMS = (@PARAMS, "-logging-mode", "a");
22136 }
22137 elsif($LogMode and $LogMode ne "w")
22138 { # "w" is default
22139 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022140 }
22141 if($ExtendedCheck) {
22142 @PARAMS = (@PARAMS, "-extended");
22143 }
22144 if($UserLang) {
22145 @PARAMS = (@PARAMS, "-lang", $UserLang);
22146 }
22147 if($TargetVersion{1}) {
22148 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22149 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022150 if($BinaryOnly) {
22151 @PARAMS = (@PARAMS, "-binary");
22152 }
22153 if($SourceOnly) {
22154 @PARAMS = (@PARAMS, "-source");
22155 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022156 if($SortDump) {
22157 @PARAMS = (@PARAMS, "-sort");
22158 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022159 if($DumpFormat and $DumpFormat ne "perl") {
22160 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22161 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022162 if($CheckHeadersOnly) {
22163 @PARAMS = (@PARAMS, "-headers-only");
22164 }
22165 if($CheckObjectsOnly) {
22166 @PARAMS = (@PARAMS, "-objects-only");
22167 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022168 if($Debug)
22169 {
22170 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022171 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022172 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022173 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022174 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022175 exit(1);
22176 }
22177 }
22178 else
22179 { # child
22180 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22181 if($RelativeDirectory{2}) {
22182 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22183 }
22184 if($OutputLogPath{2}) {
22185 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22186 }
22187 if($CrossGcc) {
22188 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22189 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022190 if($Quiet)
22191 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022192 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022193 @PARAMS = (@PARAMS, "-logging-mode", "a");
22194 }
22195 elsif($LogMode and $LogMode ne "w")
22196 { # "w" is default
22197 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022198 }
22199 if($ExtendedCheck) {
22200 @PARAMS = (@PARAMS, "-extended");
22201 }
22202 if($UserLang) {
22203 @PARAMS = (@PARAMS, "-lang", $UserLang);
22204 }
22205 if($TargetVersion{2}) {
22206 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22207 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022208 if($BinaryOnly) {
22209 @PARAMS = (@PARAMS, "-binary");
22210 }
22211 if($SourceOnly) {
22212 @PARAMS = (@PARAMS, "-source");
22213 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022214 if($SortDump) {
22215 @PARAMS = (@PARAMS, "-sort");
22216 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022217 if($DumpFormat and $DumpFormat ne "perl") {
22218 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22219 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022220 if($CheckHeadersOnly) {
22221 @PARAMS = (@PARAMS, "-headers-only");
22222 }
22223 if($CheckObjectsOnly) {
22224 @PARAMS = (@PARAMS, "-objects-only");
22225 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022226 if($Debug)
22227 {
22228 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022229 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022230 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022231 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022232 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022233 exit(1);
22234 }
22235 else {
22236 exit(0);
22237 }
22238 }
22239 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022240
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022241 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022242 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22243 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022244 if($TargetTitle ne $TargetLibraryName) {
22245 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022246 }
22247 if($ShowRetVal) {
22248 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22249 }
22250 if($CrossGcc) {
22251 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22252 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022253 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22254 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022255 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022256 }
22257 if($ReportFormat and $ReportFormat ne "html")
22258 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022259 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22260 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022261 if($OutputReportPath) {
22262 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22263 }
22264 if($BinaryReportPath) {
22265 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22266 }
22267 if($SourceReportPath) {
22268 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22269 }
22270 if($LoggingPath) {
22271 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22272 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022273 if($CheckHeadersOnly) {
22274 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22275 }
22276 if($CheckObjectsOnly) {
22277 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
22278 }
22279 if($BinaryOnly) {
22280 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22281 }
22282 if($SourceOnly) {
22283 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22284 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022285 if($Debug)
22286 {
22287 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22288 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022289 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022290 system("perl", $0, @CMP_PARAMS);
22291 exit($?>>8);
22292 }
22293 if(not $Descriptor{1}{"Dump"}
22294 or not $Descriptor{2}{"Dump"})
22295 { # need GCC toolchain to analyze
22296 # header files and libraries
22297 detect_default_paths("inc|lib|gcc");
22298 }
22299 if(not $Descriptor{1}{"Dump"})
22300 {
22301 if(not $CheckHeadersOnly) {
22302 readLibs(1);
22303 }
22304 if($CheckHeadersOnly) {
22305 setLanguage(1, "C++");
22306 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022307 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022308 searchForHeaders(1);
22309 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022310 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022311 }
22312 if(not $Descriptor{2}{"Dump"})
22313 {
22314 if(not $CheckHeadersOnly) {
22315 readLibs(2);
22316 }
22317 if($CheckHeadersOnly) {
22318 setLanguage(2, "C++");
22319 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022320 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022321 searchForHeaders(2);
22322 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022323 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022324 }
22325 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22326 { # support for old ABI dumps
22327 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022328 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022329 {
22330 $WORD_SIZE{1} = $WORD_SIZE{2};
22331 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22332 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022333 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022334 {
22335 $WORD_SIZE{2} = $WORD_SIZE{1};
22336 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22337 }
22338 }
22339 elsif(not $WORD_SIZE{1}
22340 and not $WORD_SIZE{2})
22341 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022342 $WORD_SIZE{1} = "4";
22343 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022344 }
22345 if($Descriptor{1}{"Dump"})
22346 { # support for old ABI dumps
22347 prepareTypes(1);
22348 }
22349 if($Descriptor{2}{"Dump"})
22350 { # support for old ABI dumps
22351 prepareTypes(2);
22352 }
22353 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22354 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22355 }
22356 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022357 if(not $CheckObjectsOnly)
22358 {
22359 if($Descriptor{1}{"Headers"}
22360 and not $Descriptor{1}{"Dump"}) {
22361 readHeaders(1);
22362 }
22363 if($Descriptor{2}{"Headers"}
22364 and not $Descriptor{2}{"Dump"}) {
22365 readHeaders(2);
22366 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022367 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022368
22369 # clean memory
22370 %SystemHeaders = ();
22371 %mangled_name_gcc = ();
22372
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022373 prepareSymbols(1);
22374 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022375
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022376 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022377 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022378
22379 # Virtual Tables
22380 registerVTable(1);
22381 registerVTable(2);
22382
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022383 if(not checkDump(1, "1.22")
22384 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022385 { # support for old ABI dumps
22386 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22387 {
22388 if($ClassName=~/</)
22389 { # templates
22390 if(not defined $VirtualTable{1}{$ClassName})
22391 { # synchronize
22392 delete($VirtualTable{2}{$ClassName});
22393 }
22394 }
22395 }
22396 }
22397
22398 registerOverriding(1);
22399 registerOverriding(2);
22400
22401 setVirtFuncPositions(1);
22402 setVirtFuncPositions(2);
22403
22404 # Other
22405 addParamNames(1);
22406 addParamNames(2);
22407
22408 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022409}
22410
22411sub compareAPIs($)
22412{
22413 my $Level = $_[0];
22414 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022415 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022416 if($Level eq "Binary") {
22417 printMsg("INFO", "comparing ABIs ...");
22418 }
22419 else {
22420 printMsg("INFO", "comparing APIs ...");
22421 }
22422 if($CheckHeadersOnly
22423 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022424 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022425 detectAdded_H($Level);
22426 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022427 }
22428 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022429 { # added/removed in libs
22430 detectAdded($Level);
22431 detectRemoved($Level);
22432 }
22433 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022434 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022435 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022436 if(keys(%{$CheckedSymbols{$Level}})) {
22437 mergeConstants($Level);
22438 }
22439 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022440
22441 $Cache{"mergeTypes"} = (); # free memory
22442
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022443 if($CheckHeadersOnly
22444 or $Level eq "Source")
22445 { # added/removed in headers
22446 mergeHeaders($Level);
22447 }
22448 else
22449 { # added/removed in libs
22450 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022451 }
22452}
22453
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022454sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022455{
22456 my %Opts = (
22457 "OStarget"=>$OStarget,
22458 "Debug"=>$Debug,
22459 "Quiet"=>$Quiet,
22460 "LogMode"=>$LogMode,
22461 "CheckHeadersOnly"=>$CheckHeadersOnly,
22462
22463 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022464 "GCC_PATH"=>$GCC_PATH,
22465 "TargetSysInfo"=>$TargetSysInfo,
22466 "CrossPrefix"=>$CrossPrefix,
22467 "TargetLibraryName"=>$TargetLibraryName,
22468 "CrossGcc"=>$CrossGcc,
22469 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022470 "NoStdInc"=>$NoStdInc,
22471
22472 "BinaryOnly" => $BinaryOnly,
22473 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022474 );
22475 return \%Opts;
22476}
22477
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022478sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022479{
22480 my %CODE_ERROR = reverse(%ERROR_CODE);
22481 return $CODE_ERROR{$_[0]};
22482}
22483
22484sub scenario()
22485{
22486 if($StdOut)
22487 { # enable quiet mode
22488 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022489 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022490 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022491 if(not $LogMode)
22492 { # default
22493 $LogMode = "w";
22494 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022495 if($UserLang)
22496 { # --lang=C++
22497 $UserLang = uc($UserLang);
22498 $COMMON_LANGUAGE{1}=$UserLang;
22499 $COMMON_LANGUAGE{2}=$UserLang;
22500 }
22501 if($LoggingPath)
22502 {
22503 $OutputLogPath{1} = $LoggingPath;
22504 $OutputLogPath{2} = $LoggingPath;
22505 if($Quiet) {
22506 $COMMON_LOG_PATH = $LoggingPath;
22507 }
22508 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022509 if($Quick) {
22510 $ADD_TMPL_INSTANCES = 0;
22511 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022512 if($OutputDumpPath)
22513 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022514 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022515 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22516 }
22517 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022518 if($BinaryOnly and $SourceOnly)
22519 { # both --binary and --source
22520 # is the default mode
22521 $DoubleReport = 1;
22522 $JoinReport = 0;
22523 $BinaryOnly = 0;
22524 $SourceOnly = 0;
22525 if($OutputReportPath)
22526 { # --report-path
22527 $DoubleReport = 0;
22528 $JoinReport = 1;
22529 }
22530 }
22531 elsif($BinaryOnly or $SourceOnly)
22532 { # --binary or --source
22533 $DoubleReport = 0;
22534 $JoinReport = 0;
22535 }
22536 if($UseXML)
22537 { # --xml option
22538 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022539 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022540 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022541 if($ReportFormat)
22542 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022543 $ReportFormat = lc($ReportFormat);
22544 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022545 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022546 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022547 if($ReportFormat eq "htm")
22548 { # HTM == HTML
22549 $ReportFormat = "html";
22550 }
22551 elsif($ReportFormat eq "xml")
22552 { # --report-format=XML equal to --xml
22553 $UseXML = 1;
22554 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022555 }
22556 else
22557 { # default: HTML
22558 $ReportFormat = "html";
22559 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022560 if($DumpFormat)
22561 { # validate
22562 $DumpFormat = lc($DumpFormat);
22563 if($DumpFormat!~/\A(xml|perl)\Z/) {
22564 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22565 }
22566 if($DumpFormat eq "xml")
22567 { # --dump-format=XML equal to --xml
22568 $UseXML = 1;
22569 }
22570 }
22571 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022572 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022573 $DumpFormat = "perl";
22574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022575 if($Quiet and $LogMode!~/a|n/)
22576 { # --quiet log
22577 if(-f $COMMON_LOG_PATH) {
22578 unlink($COMMON_LOG_PATH);
22579 }
22580 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022581 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022582 $CheckUndefined = 1;
22583 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022584 if($TestTool and $UseDumps)
22585 { # --test && --use-dumps == --test-dump
22586 $TestDump = 1;
22587 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022588 if($Tolerant)
22589 { # enable all
22590 $Tolerance = 1234;
22591 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022592 if($Help)
22593 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022594 HELP_MESSAGE();
22595 exit(0);
22596 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022597 if($InfoMsg)
22598 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022599 INFO_MESSAGE();
22600 exit(0);
22601 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022602 if($ShowVersion)
22603 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022604 printMsg("INFO", "ABI Compliance Checker (ABICC) $TOOL_VERSION\nCopyright (C) 2015 Andrey Ponomarenko's ABI Laboratory\nLicense: LGPL or GPL <http://www.gnu.org/licenses/>\nThis program is free software: you can redistribute it and/or modify it.\n\nWritten by Andrey Ponomarenko.");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022605 exit(0);
22606 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022607 if($DumpVersion)
22608 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022609 printMsg("INFO", $TOOL_VERSION);
22610 exit(0);
22611 }
22612 if($ExtendedCheck) {
22613 $CheckHeadersOnly = 1;
22614 }
22615 if($SystemRoot_Opt)
22616 { # user defined root
22617 if(not -e $SystemRoot_Opt) {
22618 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22619 }
22620 $SystemRoot = $SystemRoot_Opt;
22621 $SystemRoot=~s/[\/]+\Z//g;
22622 if($SystemRoot) {
22623 $SystemRoot = get_abs_path($SystemRoot);
22624 }
22625 }
22626 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022627
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022628 if($SortDump)
22629 {
22630 $Data::Dumper::Useperl = 1;
22631 $Data::Dumper::Sortkeys = \&dump_sorting;
22632 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022633
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022634 if($TargetLibsPath)
22635 {
22636 if(not -f $TargetLibsPath) {
22637 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22638 }
22639 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22640 $TargetLibs{$Lib} = 1;
22641 }
22642 }
22643 if($TargetHeadersPath)
22644 { # --headers-list
22645 if(not -f $TargetHeadersPath) {
22646 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22647 }
22648 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22649 {
22650 $TargetHeaders{1}{$Header} = 1;
22651 $TargetHeaders{2}{$Header} = 1;
22652 }
22653 }
22654 if($TargetHeader)
22655 { # --header
22656 $TargetHeaders{1}{$TargetHeader} = 1;
22657 $TargetHeaders{2}{$TargetHeader} = 1;
22658 }
22659 if($TestTool
22660 or $TestDump)
22661 { # --test, --test-dump
22662 detect_default_paths("bin|gcc"); # to compile libs
22663 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022664 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022665 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022666 exit(0);
22667 }
22668 if($DumpSystem)
22669 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022670
22671 if(not $TargetSysInfo) {
22672 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22673 }
22674
22675 if(not -d $TargetSysInfo) {
22676 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22677 }
22678
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022679 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022680 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022681 { # system XML descriptor
22682 if(not -f $DumpSystem) {
22683 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22684 }
22685 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022686 foreach (@{$Ret->{"Tools"}})
22687 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022688 push_U($SystemPaths{"bin"}, $_);
22689 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022690 }
22691 if($Ret->{"CrossPrefix"}) {
22692 $CrossPrefix = $Ret->{"CrossPrefix"};
22693 }
22694 }
22695 elsif($SystemRoot_Opt)
22696 { # -sysroot "/" option
22697 # default target: /usr/lib, /usr/include
22698 # search libs: /usr/lib and /lib
22699 if(not -e $SystemRoot."/usr/lib") {
22700 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22701 }
22702 if(not -e $SystemRoot."/lib") {
22703 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22704 }
22705 if(not -e $SystemRoot."/usr/include") {
22706 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22707 }
22708 readSystemDescriptor("
22709 <name>
22710 $DumpSystem
22711 </name>
22712 <headers>
22713 $SystemRoot/usr/include
22714 </headers>
22715 <libs>
22716 $SystemRoot/usr/lib
22717 </libs>
22718 <search_libs>
22719 $SystemRoot/lib
22720 </search_libs>");
22721 }
22722 else {
22723 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22724 }
22725 detect_default_paths("bin|gcc"); # to check symbols
22726 if($OStarget eq "windows")
22727 { # to run dumpbin.exe
22728 # and undname.exe
22729 check_win32_env();
22730 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022731 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022732 exit(0);
22733 }
22734 if($CmpSystems)
22735 { # --cmp-systems
22736 detect_default_paths("bin"); # to extract dumps
22737 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022738 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022739 exit(0);
22740 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022741 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022742 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022743 }
22744 else
22745 { # validate library name
22746 if($TargetLibraryName=~/[\*\/\\]/) {
22747 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22748 }
22749 }
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022750 if(not $TargetTitle) {
22751 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022752 }
22753 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
22754 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
22755 }
22756 if($SymbolsListPath)
22757 {
22758 if(not -f $SymbolsListPath) {
22759 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22760 }
22761 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22762 $SymbolsList{$Interface} = 1;
22763 }
22764 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022765 if($TypesListPath)
22766 {
22767 if(not -f $TypesListPath) {
22768 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22769 }
22770 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22771 $TypesList{$Type} = 1;
22772 }
22773 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022774 if($SkipSymbolsListPath)
22775 {
22776 if(not -f $SkipSymbolsListPath) {
22777 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22778 }
22779 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022780 $SkipSymbols{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022781 }
22782 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022783 if($SkipHeadersPath)
22784 {
22785 if(not -f $SkipHeadersPath) {
22786 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22787 }
22788 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022789 { # register for both versions
22790 $SkipHeadersList{1}{$Path} = 1;
22791 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022792 my ($CPath, $Type) = classifyPath($Path);
22793 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022794 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022795 }
22796 }
22797 if($ParamNamesPath)
22798 {
22799 if(not -f $ParamNamesPath) {
22800 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22801 }
22802 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22803 {
22804 if($Line=~s/\A(\w+)\;//)
22805 {
22806 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022807 if($Line=~/;(\d+);/)
22808 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022809 while($Line=~s/(\d+);(\w+)//) {
22810 $AddIntParams{$Interface}{$1}=$2;
22811 }
22812 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022813 else
22814 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022815 my $Num = 0;
22816 foreach my $Name (split(/;/, $Line)) {
22817 $AddIntParams{$Interface}{$Num++}=$Name;
22818 }
22819 }
22820 }
22821 }
22822 }
22823 if($AppPath)
22824 {
22825 if(not -f $AppPath) {
22826 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22827 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022828 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022829 $SymbolsList_App{$Interface} = 1;
22830 }
22831 }
22832 if($DumpAPI)
22833 { # --dump-abi
22834 # make an API dump
22835 create_ABI_Dump();
22836 exit($COMPILE_ERRORS);
22837 }
22838 # default: compare APIs
22839 # -d1 <path>
22840 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022841 compareInit();
22842 if($JoinReport or $DoubleReport)
22843 {
22844 compareAPIs("Binary");
22845 compareAPIs("Source");
22846 }
22847 elsif($BinaryOnly) {
22848 compareAPIs("Binary");
22849 }
22850 elsif($SourceOnly) {
22851 compareAPIs("Source");
22852 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022853 exitReport();
22854}
22855
22856scenario();