blob: 590c66bab140051301dec11368ff48d25d8cc0f7 [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 Ponomarenko01e8e502015-08-21 22:08:40 +030074my $LOCALE = "LANG=en_US.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 Ponomarenkoab282102012-03-11 11:57:02 +04001486# OS Compliance
1487my %TargetLibs;
1488my %TargetHeaders;
1489
1490# OS Specifics
1491my $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}}))
6544 { # all names are differend with current prefix
6545 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 {
8745 my $DirCmd = get_CmdPath("dir");
8746 if(not $DirCmd) {
8747 exitStatus("Not_Found", "can't find \"dir\" command");
8748 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008749 $Path = get_abs_path($Path);
8750 $Path = path_format($Path, $OSgroup);
8751 my $Cmd = $DirCmd." \"$Path\" /B /O";
8752 if($MaxDepth!=1) {
8753 $Cmd .= " /S";
8754 }
8755 if($Type eq "d") {
8756 $Cmd .= " /AD";
8757 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008758 elsif($Type eq "f") {
8759 $Cmd .= " /A-D";
8760 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008761 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008762 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008763 {
8764 if(not $UseRegex)
8765 { # FIXME: how to search file names in MS shell?
8766 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008767 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008768 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008769 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008770 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008771 }
8772 my @AbsPaths = ();
8773 foreach my $File (@Files)
8774 {
8775 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008776 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008777 }
8778 if($Type eq "f" and not -f $File)
8779 { # skip dirs
8780 next;
8781 }
8782 push(@AbsPaths, path_format($File, $OSgroup));
8783 }
8784 if($Type eq "d") {
8785 push(@AbsPaths, $Path);
8786 }
8787 return @AbsPaths;
8788 }
8789 else
8790 {
8791 my $FindCmd = get_CmdPath("find");
8792 if(not $FindCmd) {
8793 exitStatus("Not_Found", "can't find a \"find\" command");
8794 }
8795 $Path = get_abs_path($Path);
8796 if(-d $Path and -l $Path
8797 and $Path!~/\/\Z/)
8798 { # for directories that are symlinks
8799 $Path.="/";
8800 }
8801 my $Cmd = $FindCmd." \"$Path\"";
8802 if($MaxDepth) {
8803 $Cmd .= " -maxdepth $MaxDepth";
8804 }
8805 if($Type) {
8806 $Cmd .= " -type $Type";
8807 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008808 if($Name and not $UseRegex)
8809 { # wildcards
8810 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008811 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008812 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008813 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008814 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8815 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008816 my @Files = split(/\n/, $Res);
8817 if($Name and $UseRegex)
8818 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008819 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008820 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008821 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008822 }
8823}
8824
8825sub unpackDump($)
8826{
8827 my $Path = $_[0];
8828 return "" if(not $Path or not -e $Path);
8829 $Path = get_abs_path($Path);
8830 $Path = path_format($Path, $OSgroup);
8831 my ($Dir, $FileName) = separate_path($Path);
8832 my $UnpackDir = $TMP_DIR."/unpack";
8833 rmtree($UnpackDir);
8834 mkpath($UnpackDir);
8835 if($FileName=~s/\Q.zip\E\Z//g)
8836 { # *.zip
8837 my $UnzipCmd = get_CmdPath("unzip");
8838 if(not $UnzipCmd) {
8839 exitStatus("Not_Found", "can't find \"unzip\" command");
8840 }
8841 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008842 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008843 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008844 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008845 }
8846 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008847 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008848 if(not @Contents) {
8849 exitStatus("Error", "can't extract \'$Path\'");
8850 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008851 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008852 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008853 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008854 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008855 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008856 if($OSgroup eq "windows")
8857 { # -xvzf option is not implemented in tar.exe (2003)
8858 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8859 my $TarCmd = get_CmdPath("tar");
8860 if(not $TarCmd) {
8861 exitStatus("Not_Found", "can't find \"tar\" command");
8862 }
8863 my $GzipCmd = get_CmdPath("gzip");
8864 if(not $GzipCmd) {
8865 exitStatus("Not_Found", "can't find \"gzip\" command");
8866 }
8867 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008868 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008869 if($?) {
8870 exitStatus("Error", "can't extract \'$Path\'");
8871 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008872 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008873 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008874 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008875 }
8876 chdir($ORIG_DIR);
8877 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008878 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008879 if(not @Contents) {
8880 exitStatus("Error", "can't extract \'$Path\'");
8881 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008882 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008883 }
8884 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008885 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008886 my $TarCmd = get_CmdPath("tar");
8887 if(not $TarCmd) {
8888 exitStatus("Not_Found", "can't find \"tar\" command");
8889 }
8890 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008891 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008892 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008893 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008894 }
8895 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008896 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008897 if(not @Contents) {
8898 exitStatus("Error", "can't extract \'$Path\'");
8899 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008900 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008901 }
8902 }
8903}
8904
8905sub createArchive($$)
8906{
8907 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008908 if(not $To) {
8909 $To = ".";
8910 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008911 if(not $Path or not -e $Path
8912 or not -d $To) {
8913 return "";
8914 }
8915 my ($From, $Name) = separate_path($Path);
8916 if($OSgroup eq "windows")
8917 { # *.zip
8918 my $ZipCmd = get_CmdPath("zip");
8919 if(not $ZipCmd) {
8920 exitStatus("Not_Found", "can't find \"zip\"");
8921 }
8922 my $Pkg = $To."/".$Name.".zip";
8923 unlink($Pkg);
8924 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008925 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008926 if($?)
8927 { # cannot allocate memory (or other problems with "zip")
8928 unlink($Path);
8929 exitStatus("Error", "can't pack the ABI dump: ".$!);
8930 }
8931 chdir($ORIG_DIR);
8932 unlink($Path);
8933 return $Pkg;
8934 }
8935 else
8936 { # *.tar.gz
8937 my $TarCmd = get_CmdPath("tar");
8938 if(not $TarCmd) {
8939 exitStatus("Not_Found", "can't find \"tar\"");
8940 }
8941 my $GzipCmd = get_CmdPath("gzip");
8942 if(not $GzipCmd) {
8943 exitStatus("Not_Found", "can't find \"gzip\"");
8944 }
8945 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8946 unlink($Pkg);
8947 chdir($From);
8948 system($TarCmd, "-czf", $Pkg, $Name);
8949 if($?)
8950 { # cannot allocate memory (or other problems with "tar")
8951 unlink($Path);
8952 exitStatus("Error", "can't pack the ABI dump: ".$!);
8953 }
8954 chdir($ORIG_DIR);
8955 unlink($Path);
8956 return $To."/".$Name.".tar.gz";
8957 }
8958}
8959
8960sub is_header_file($)
8961{
8962 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8963 return $_[0];
8964 }
8965 return 0;
8966}
8967
8968sub is_not_header($)
8969{
8970 if($_[0]=~/\.\w+\Z/
8971 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8972 return 1;
8973 }
8974 return 0;
8975}
8976
8977sub is_header($$$)
8978{
8979 my ($Header, $UserDefined, $LibVersion) = @_;
8980 return 0 if(-d $Header);
8981 if(-f $Header) {
8982 $Header = get_abs_path($Header);
8983 }
8984 else
8985 {
8986 if(is_abs($Header))
8987 { # incorrect absolute path
8988 return 0;
8989 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008990 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008991 $Header = $HPath;
8992 }
8993 else
8994 { # can't find header
8995 return 0;
8996 }
8997 }
8998 if($Header=~/\.\w+\Z/)
8999 { # have an extension
9000 return is_header_file($Header);
9001 }
9002 else
9003 {
9004 if($UserDefined==2)
9005 { # specified on the command line
9006 if(cmd_file($Header)!~/HTML|XML/i) {
9007 return $Header;
9008 }
9009 }
9010 elsif($UserDefined)
9011 { # specified in the XML-descriptor
9012 # header file without an extension
9013 return $Header;
9014 }
9015 else
9016 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009017 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009018 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009019 { # !~/HTML|XML|shared|dynamic/i
9020 return $Header;
9021 }
9022 }
9023 }
9024 return 0;
9025}
9026
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009027sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009028{
9029 my $LibVersion = $_[0];
9030 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9031 {
9032 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009033 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009034
9035 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9036 detect_recursive_includes($RegHeader, $LibVersion);
9037 }
9038
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009039 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9040 {
9041 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009042
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009043 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009044 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9045 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009046 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009047 }
9048 }
9049 }
9050}
9051
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009052sub familiarDirs($$)
9053{
9054 my ($D1, $D2) = @_;
9055 if($D1 eq $D2) {
9056 return 1;
9057 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009058
9059 my $U1 = index($D1, "/usr/");
9060 my $U2 = index($D2, "/usr/");
9061
9062 if($U1==0 and $U2!=0) {
9063 return 0;
9064 }
9065
9066 if($U2==0 and $U1!=0) {
9067 return 0;
9068 }
9069
9070 if(index($D2, $D1."/")==0) {
9071 return 1;
9072 }
9073
9074 # /usr/include/DIR
9075 # /home/user/DIR
9076
9077 my $DL = get_depth($D1);
9078
9079 my @Dirs1 = ($D1);
9080 while($DL - get_depth($D1)<=2
9081 and get_depth($D1)>=4
9082 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9083 push(@Dirs1, $D1);
9084 }
9085
9086 my @Dirs2 = ($D2);
9087 while(get_depth($D2)>=4
9088 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9089 push(@Dirs2, $D2);
9090 }
9091
9092 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009093 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009094 foreach my $P2 (@Dirs2)
9095 {
9096
9097 if($P1 eq $P2) {
9098 return 1;
9099 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009100 }
9101 }
9102 return 0;
9103}
9104
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009105sub readHeaders($)
9106{
9107 $Version = $_[0];
9108 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9109 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009110 if($Debug)
9111 { # debug mode
9112 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009113 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009114 }
9115 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009116}
9117
9118sub prepareTypes($)
9119{
9120 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009121 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009122 { # support for old ABI dumps
9123 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009124 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009125 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009126 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9127 if($TName=~/\A(\w+)::(\w+)/) {
9128 my ($P1, $P2) = ($1, $2);
9129 if($P1 eq $P2) {
9130 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009131 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009132 else {
9133 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9134 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009135 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009136 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009137 }
9138 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009139 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009140 { # support for old ABI dumps
9141 # V < 2.5: array size == "number of elements"
9142 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009143 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009144 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009145 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009146 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009147 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009148 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009149 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009150 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009151 $Size *= $Base{"Size"};
9152 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009153 }
9154 else
9155 { # array[] is a pointer
9156 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009157 }
9158 }
9159 }
9160 }
9161 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009162 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009163 { # support for old ABI dumps
9164 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009165 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009166 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009167 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009168 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009169 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009170 my %Type = get_Type($TypeId, $LibVersion);
9171 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9172 my %Type2 = get_Type($TypeId_2, $V2);
9173 if($Type{"Size"} ne $Type2{"Size"}) {
9174 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009175 }
9176 }
9177 }
9178 }
9179}
9180
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009181sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009182{
9183 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009184
9185 if(not keys(%{$SymbolInfo{$LibVersion}}))
9186 { # check if input is valid
9187 if(not $ExtendedCheck and not $CheckObjectsOnly)
9188 {
9189 if($CheckHeadersOnly) {
9190 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9191 }
9192 else {
9193 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9194 }
9195 }
9196 }
9197
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009198 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009199 if(not checkDump(1, "2.10")
9200 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009201 { # different formats
9202 $Remangle = 1;
9203 }
9204 if($CheckHeadersOnly)
9205 { # different languages
9206 if($UserLang)
9207 { # --lang=LANG for both versions
9208 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9209 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9210 {
9211 if($UserLang eq "C++")
9212 { # remangle symbols
9213 $Remangle = 1;
9214 }
9215 elsif($UserLang eq "C")
9216 { # remove mangling
9217 $Remangle = -1;
9218 }
9219 }
9220 }
9221 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009222
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009223 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009224 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009225 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009226 { # support for old ABI dumps
9227 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9228 {
9229 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9230 {
9231 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9232 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009233 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009234 if(defined $DVal and $DVal ne "")
9235 {
9236 if($TName eq "char") {
9237 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9238 }
9239 elsif($TName eq "bool") {
9240 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9241 }
9242 }
9243 }
9244 }
9245 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009246 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009247 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009248 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9249 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009250 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009251 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9252 # + support for old ABI dumps
9253 next;
9254 }
9255 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009256 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009257 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009258 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009259 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009260
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009261 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009262 if(not checkDump(1, "2.12")
9263 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009264 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009265 if($ShortName eq "operator>>")
9266 {
9267 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9268 { # corrected mangling of operator>>
9269 $SRemangle = 1;
9270 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009271 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009272 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9273 {
9274 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9275 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9276 { # corrected mangling of const global data
9277 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9278 # and incorrectly mangled by old ACC versions
9279 $SRemangle = 1;
9280 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009281 }
9282 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009283 if(not $CheckHeadersOnly)
9284 { # support for old ABI dumps
9285 if(not checkDump(1, "2.17")
9286 or not checkDump(2, "2.17"))
9287 {
9288 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9289 {
9290 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9291 {
9292 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9293 {
9294 $MnglName = $ShortName;
9295 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9296 }
9297 }
9298 }
9299 }
9300 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009301 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009302 { # support for old ABI dumps: some symbols are not mangled in old dumps
9303 # mangle both sets of symbols (old and new)
9304 # NOTE: remangling all symbols by the same mangler
9305 if($MnglName=~/\A_ZN(V|)K/)
9306 { # mangling may be incorrect on old ABI dumps
9307 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009308 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009309 }
9310 if($MnglName=~/\A_ZN(K|)V/)
9311 { # mangling may be incorrect on old ABI dumps
9312 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009313 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009314 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009315 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9316 or (not $ClassID and $CheckHeadersOnly)
9317 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9318 { # support for old ABI dumps, GCC >= 4.0
9319 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009320 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009321 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009322 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009323 $MangledNames{$LibVersion}{$MnglName} = 1;
9324 }
9325 }
9326 }
9327 elsif($Remangle==-1)
9328 { # remove mangling
9329 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009330 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009332 if(not $MnglName) {
9333 next;
9334 }
9335 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9336 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009337 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9338
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009339 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009340 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009341 { # support for old dumps
9342 # add "Volatile" attribute
9343 if($MnglName=~/_Z(K|)V/) {
9344 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9345 }
9346 }
9347 # symbol and its symlink have same signatures
9348 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009349 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009350 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009351
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009352 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9353 {
9354 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9355 if($SymVer{$LibVersion}{$Alias}) {
9356 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9357 }
9358 }
9359
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009360 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009361 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009362 }
9363 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9364 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9365 }
9366 if($ExtendedCheck)
9367 { # --ext option
9368 addExtension($LibVersion);
9369 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009370
9371 # clean memory
9372 delete($SymbolInfo{$LibVersion});
9373
9374 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009375 { # detect allocable classes with public exported constructors
9376 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009377 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009378 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009379 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009380 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009381 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9382 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009383 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009384 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009385 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009386 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009387 $AllocableClass{$LibVersion}{$ClassName} = 1;
9388 }
9389 }
9390 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009391 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009392 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009393 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009394 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009395 if($CheckHeadersOnly)
9396 {
9397 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9398 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9399 { # all symbols except non-virtual inline
9400 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9401 }
9402 }
9403 else {
9404 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009405 }
9406 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009407 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009408 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009409 }
9410 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009411 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009412 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009413 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009414 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009415 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009416 if(defined $Base{"Type"}
9417 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009418 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009419 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009420 if($Name=~/<([^<>\s]+)>/)
9421 {
9422 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9423 $ReturnedClass{$LibVersion}{$Tid} = 1;
9424 }
9425 }
9426 else {
9427 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9428 }
9429 }
9430 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009431 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009432 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009433 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009434 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009435 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009436 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009437 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009438 if($Base{"Type"}=~/Struct|Class/)
9439 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009440 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009441 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9442 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009443 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009444 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009445 }
9446 }
9447 }
9448 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009449
9450 # mapping {short name => symbols}
9451 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009452 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009453 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009454 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009455 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009456 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009457 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009458 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009459 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9460 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009461 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009462 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009463 }
9464 }
9465 }
9466 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009467
9468 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009469 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009470 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009471 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009472 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009473 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9474 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009475 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009476 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009477 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009478 $ClassNames{$LibVersion}{$TName} = 1;
9479 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009480 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009481 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9482 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009483 }
9484 }
9485 }
9486 }
9487 }
9488}
9489
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009490sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009491{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009492 my ($Tid, $LibVersion) = @_;
9493 if(not $Tid) {
9494 return $Tid;
9495 }
9496
9497 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9498 {
9499 if($TName_Tid{$LibVersion}{$Name}) {
9500 return $TName_Tid{$LibVersion}{$Name};
9501 }
9502 }
9503
9504 return $Tid;
9505}
9506
9507sub register_SymbolUsage($$$)
9508{
9509 my ($InfoId, $UsedType, $LibVersion) = @_;
9510
9511 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9512 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9513 {
9514 register_TypeUsage($RTid, $UsedType, $LibVersion);
9515 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9516 }
9517 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9518 {
9519 register_TypeUsage($FCid, $UsedType, $LibVersion);
9520 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9521
9522 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9523 { # register "this" pointer
9524 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9525 }
9526 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9527 { # register "this" pointer (const method)
9528 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9529 }
9530 }
9531 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9532 {
9533 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9534 {
9535 register_TypeUsage($PTid, $UsedType, $LibVersion);
9536 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9537 }
9538 }
9539 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9540 {
9541 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9542 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9543 register_TypeUsage($TTid, $UsedType, $LibVersion);
9544 }
9545 }
9546}
9547
9548sub register_TypeUsage($$$)
9549{
9550 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009551 if(not $TypeId) {
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 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009555 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009556 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009557 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009558
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009559 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009560 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009561 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009562 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009563 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009564 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9565 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9566 }
9567 }
9568
9569 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9570 {
9571 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009572 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009573 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009574 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9575 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009576 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009577 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9578 {
9579 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9580 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009581 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009582 }
9583 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009584 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009585 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009586 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009587 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9588 {
9589 register_TypeUsage($MTid, $UsedType, $LibVersion);
9590 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009591 }
9592 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009593 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009594 or $TInfo{"Type"} eq "MethodPtr"
9595 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009596 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009597 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009598 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009599 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009600 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009601 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009602 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9603 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009604 }
9605 }
9606 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009607 if($TInfo{"Type"} eq "FieldPtr")
9608 {
9609 if(my $RTid = $TInfo{"Return"}) {
9610 register_TypeUsage($RTid, $UsedType, $LibVersion);
9611 }
9612 if(my $CTid = $TInfo{"Class"}) {
9613 register_TypeUsage($CTid, $UsedType, $LibVersion);
9614 }
9615 }
9616 if($TInfo{"Type"} eq "MethodPtr")
9617 {
9618 if(my $CTid = $TInfo{"Class"}) {
9619 register_TypeUsage($CTid, $UsedType, $LibVersion);
9620 }
9621 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009622 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009623 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009624 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009625 $UsedType->{$TypeId} = 1;
9626 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9627 {
9628 register_TypeUsage($BTid, $UsedType, $LibVersion);
9629 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9630 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009631 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009632 else
9633 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9634 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009635 }
9636 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009637}
9638
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009639sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009640{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009641 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9642
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009643 if($Level eq "Dump")
9644 {
9645 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9646 { # TODO: check if this symbol is from
9647 # base classes of other target symbols
9648 return 1;
9649 }
9650 }
9651
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009652 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9653 { # stdc++ interfaces
9654 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009655 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009656
9657 my $Target = 0;
9658 if(my $Header = $SInfo->{"Header"}) {
9659 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9660 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009661 if($ExtendedCheck)
9662 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009663 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009664 $Target = 1;
9665 }
9666 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009667 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009668 {
9669 if($Target)
9670 {
9671 if($Level eq "Dump")
9672 { # dumped
9673 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009674 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009675 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009676 return 1;
9677 }
9678 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009679 else {
9680 return 1;
9681 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009682 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009683 elsif($Level eq "Source")
9684 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009685 return 1;
9686 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009687 elsif($Level eq "Binary")
9688 { # checked
9689 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9690 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9691 return 1;
9692 }
9693 }
9694 }
9695 }
9696 else
9697 { # library is available
9698 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9699 { # exported symbols
9700 return 1;
9701 }
9702 if($Level eq "Dump")
9703 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009704 if($BinaryOnly)
9705 {
9706 if($SInfo->{"Data"})
9707 {
9708 if($Target) {
9709 return 1;
9710 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009711 }
9712 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009713 else
9714 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009715 if($Target) {
9716 return 1;
9717 }
9718 }
9719 }
9720 elsif($Level eq "Source")
9721 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009722 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
9723 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009724 { # skip LOCAL symbols
9725 if($Target) {
9726 return 1;
9727 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009728 }
9729 }
9730 elsif($Level eq "Binary")
9731 { # checked
9732 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9733 {
9734 if($Target) {
9735 return 1;
9736 }
9737 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009738 }
9739 }
9740 return 0;
9741}
9742
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009743sub cleanDump($)
9744{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009745 my $LibVersion = $_[0];
9746 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9747 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009748 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9749 {
9750 delete($SymbolInfo{$LibVersion}{$InfoId});
9751 next;
9752 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009753 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009754 if(not $MnglName)
9755 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009756 delete($SymbolInfo{$LibVersion}{$InfoId});
9757 next;
9758 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009759 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009760 if(not $ShortName)
9761 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009762 delete($SymbolInfo{$LibVersion}{$InfoId});
9763 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009764 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009765 if($MnglName eq $ShortName)
9766 { # remove duplicate data
9767 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009768 }
9769 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9770 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9771 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009772 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9773 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9774 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009775 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009776 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009777 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009778 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009779 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9780 {
9781 delete($TypeInfo{$LibVersion}{$Tid});
9782 next;
9783 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009784 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009785 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009786 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009787 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9788 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9789 }
9790 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009791 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9792 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9793 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009794 }
9795}
9796
9797sub selectType($$)
9798{
9799 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009800
9801 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9802 {
9803 if(defined $TypeInfo{$LibVersion}{$Dupl})
9804 {
9805 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9806 { # duplicate
9807 return 0;
9808 }
9809 }
9810 }
9811
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009812 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9813 {
9814 if(not isBuiltIn($THeader))
9815 {
9816 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009817 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009818 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9819 {
9820 if(is_target_header($THeader, $LibVersion))
9821 { # from target headers
9822 if(not selfTypedef($Tid, $LibVersion)) {
9823 return 1;
9824 }
9825 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009826 }
9827 }
9828 }
9829 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009830 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009831}
9832
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009833sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009834{ # remove unused data types from the ABI dump
9835 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009836
9837 my %UsedType = ();
9838
9839 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009840 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009841 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009842 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009843 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009844 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009845 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009846 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009847 next;
9848 }
9849
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009850 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009851 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009852 if(selectType($Tid, $LibVersion))
9853 {
9854 my %Tree = ();
9855 register_TypeUsage($Tid, \%Tree, $LibVersion);
9856
9857 my $Tmpl = 0;
9858 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9859 {
9860 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9861 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9862 {
9863 $Tmpl = 1;
9864 last;
9865 }
9866 }
9867 if(not $Tmpl)
9868 {
9869 foreach (keys(%Tree)) {
9870 $UsedType{$_} = 1;
9871 }
9872 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009873 }
9874 }
9875 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009876
9877 my %Delete = ();
9878
9879 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009880 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009881 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009882 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009883 next;
9884 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009885
9886 if($Kind eq "Extra")
9887 {
9888 my %Tree = ();
9889 register_TypeUsage($Tid, \%Tree, $LibVersion);
9890
9891 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9892 {
9893 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9894 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9895 {
9896 $Delete{$Tid} = 1;
9897 last;
9898 }
9899 }
9900 }
9901 else
9902 {
9903 # remove type
9904 delete($TypeInfo{$LibVersion}{$Tid});
9905 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009906 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009907
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009908 if($Kind eq "Extra")
9909 { # remove duplicates
9910 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9911 {
9912 if($UsedType{$Tid})
9913 { # All & Extended
9914 next;
9915 }
9916
9917 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9918
9919 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9920 delete($TypeInfo{$LibVersion}{$Tid});
9921 }
9922 }
9923 }
9924
9925 foreach my $Tid (keys(%Delete))
9926 {
9927 delete($TypeInfo{$LibVersion}{$Tid});
9928 }
9929}
9930
9931sub check_Completeness($$)
9932{
9933 my ($Info, $LibVersion) = @_;
9934
9935 # data types
9936 if(defined $Info->{"Memb"})
9937 {
9938 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9939 {
9940 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9941 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9942 }
9943 }
9944 }
9945 if(defined $Info->{"Base"})
9946 {
9947 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9948 check_TypeInfo($Bid, $LibVersion);
9949 }
9950 }
9951 if(defined $Info->{"BaseType"}) {
9952 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9953 }
9954 if(defined $Info->{"TParam"})
9955 {
9956 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9957 {
9958 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9959 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9960 next;
9961 }
9962 if($TName eq "_BoolType") {
9963 next;
9964 }
9965 if($TName=~/\Asizeof\(/) {
9966 next;
9967 }
9968 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9969 check_TypeInfo($Tid, $LibVersion);
9970 }
9971 else
9972 {
9973 if(defined $Debug) {
9974 printMsg("WARNING", "missed type $TName");
9975 }
9976 }
9977 }
9978 }
9979
9980 # symbols
9981 if(defined $Info->{"Param"})
9982 {
9983 foreach my $Pos (keys(%{$Info->{"Param"}}))
9984 {
9985 if(defined $Info->{"Param"}{$Pos}{"type"}) {
9986 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
9987 }
9988 }
9989 }
9990 if(defined $Info->{"Return"}) {
9991 check_TypeInfo($Info->{"Return"}, $LibVersion);
9992 }
9993 if(defined $Info->{"Class"}) {
9994 check_TypeInfo($Info->{"Class"}, $LibVersion);
9995 }
9996}
9997
9998sub check_TypeInfo($$)
9999{
10000 my ($Tid, $LibVersion) = @_;
10001
10002 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10003 return;
10004 }
10005 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10006
10007 if(defined $TypeInfo{$LibVersion}{$Tid})
10008 {
10009 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10010 printMsg("ERROR", "missed type name ($Tid)");
10011 }
10012 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10013 }
10014 else {
10015 printMsg("ERROR", "missed type id $Tid");
10016 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010017}
10018
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010019sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010020{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010021 my ($TypeId, $LibVersion) = @_;
10022 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010023 if($Type{"Type"} eq "Typedef")
10024 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010025 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010026 if($Base{"Type"}=~/Class|Struct/)
10027 {
10028 if($Type{"Name"} eq $Base{"Name"}) {
10029 return 1;
10030 }
10031 elsif($Type{"Name"}=~/::(\w+)\Z/)
10032 {
10033 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10034 { # QPointer<QWidget>::QPointer
10035 return 1;
10036 }
10037 }
10038 }
10039 }
10040 return 0;
10041}
10042
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010043sub addExtension($)
10044{
10045 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010046 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010047 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010048 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010049 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010050 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10051 $TName=~s/\A(struct|union|class|enum) //;
10052 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010053
10054 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10055 "Header" => "extended.h",
10056 "ShortName" => $Symbol,
10057 "MnglName" => $Symbol,
10058 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10059 );
10060
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010061 $ExtendedSymbols{$Symbol} = 1;
10062 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10063 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010064 }
10065 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010066 $ExtendedSymbols{"external_func_0"} = 1;
10067 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10068 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010069}
10070
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010071sub findMethod($$$)
10072{
10073 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010074 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010075 {
10076 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10077 return $VirtMethodInClass;
10078 }
10079 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10080 return $VirtMethodInBaseClasses;
10081 }
10082 }
10083 return "";
10084}
10085
10086sub findMethod_Class($$$)
10087{
10088 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010089 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010090 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10091 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10092 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10093 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10094 { # search for interface with the same parameters suffix (overridden)
10095 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10096 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010097 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10098 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010099 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10100 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010101 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10102 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10103 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10104 return $Candidate;
10105 }
10106 }
10107 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010108 else
10109 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010110 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10111 return $Candidate;
10112 }
10113 }
10114 }
10115 }
10116 return "";
10117}
10118
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010119sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010120{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010121 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010122 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010123 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010124 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10125 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010126 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010127 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010128 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010129 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10130 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010131 { # pure virtual D2-destructors are marked as "virt" in the dump
10132 # virtual D2-destructors are NOT marked as "virt" in the dump
10133 # both destructors are not presented in the v-table
10134 next;
10135 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010136 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010137 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10138 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010139 }
10140}
10141
10142sub registerOverriding($)
10143{
10144 my $LibVersion = $_[0];
10145 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010146 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010147 foreach my $ClassName (@Classes)
10148 {
10149 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10150 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010151 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10152 { # pure virtuals
10153 next;
10154 }
10155 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10156 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010157 {
10158 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10159 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10160 { # both overridden virtual methods
10161 # and implemented pure virtual methods
10162 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10163 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10164 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10165 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010166 }
10167 }
10168 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10169 delete($VirtualTable{$LibVersion}{$ClassName});
10170 }
10171 }
10172}
10173
10174sub setVirtFuncPositions($)
10175{
10176 my $LibVersion = $_[0];
10177 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10178 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010179 my ($Num, $Rel) = (1, 0);
10180
10181 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010182 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010183 if($UsedDump{$LibVersion}{"DWARF"}) {
10184 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10185 }
10186 else {
10187 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10188 }
10189 foreach my $VirtFunc (@Funcs)
10190 {
10191 if($UsedDump{$LibVersion}{"DWARF"}) {
10192 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10193 }
10194 else {
10195 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10196 }
10197
10198 # set relative positions
10199 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10200 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10201 { # relative position excluding added and removed virtual functions
10202 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10203 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10204 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10205 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010206 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010207 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010208 }
10209 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010210 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010211 {
10212 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010213 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010214 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010215 }
10216 }
10217}
10218
10219sub get_sub_classes($$$)
10220{
10221 my ($ClassId, $LibVersion, $Recursive) = @_;
10222 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10223 my @Subs = ();
10224 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10225 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010226 if($Recursive)
10227 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010228 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10229 push(@Subs, $SubSubId);
10230 }
10231 }
10232 push(@Subs, $SubId);
10233 }
10234 return @Subs;
10235}
10236
10237sub get_base_classes($$$)
10238{
10239 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010240 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010241 return () if(not defined $ClassType{"Base"});
10242 my @Bases = ();
10243 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10244 keys(%{$ClassType{"Base"}}))
10245 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010246 if($Recursive)
10247 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010248 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10249 push(@Bases, $SubBaseId);
10250 }
10251 }
10252 push(@Bases, $BaseId);
10253 }
10254 return @Bases;
10255}
10256
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010257sub getVTable_Model($$)
10258{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010259 my ($ClassId, $LibVersion) = @_;
10260 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10261 my @Elements = ();
10262 foreach my $BaseId (@Bases, $ClassId)
10263 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010264 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010265 {
10266 if(defined $VirtualTable{$LibVersion}{$BName})
10267 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010268 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10269 if($UsedDump{$LibVersion}{"DWARF"}) {
10270 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10271 }
10272 else {
10273 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10274 }
10275 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010276 push(@Elements, $VFunc);
10277 }
10278 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010279 }
10280 }
10281 return @Elements;
10282}
10283
10284sub getVShift($$)
10285{
10286 my ($ClassId, $LibVersion) = @_;
10287 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10288 my $VShift = 0;
10289 foreach my $BaseId (@Bases)
10290 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010291 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010292 {
10293 if(defined $VirtualTable{$LibVersion}{$BName}) {
10294 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10295 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010296 }
10297 }
10298 return $VShift;
10299}
10300
10301sub getShift($$)
10302{
10303 my ($ClassId, $LibVersion) = @_;
10304 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10305 my $Shift = 0;
10306 foreach my $BaseId (@Bases)
10307 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010308 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010309 {
10310 if($Size!=1)
10311 { # not empty base class
10312 $Shift+=$Size;
10313 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010314 }
10315 }
10316 return $Shift;
10317}
10318
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010319sub getVTable_Size($$)
10320{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010321 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010322 my $Size = 0;
10323 # three approaches
10324 if(not $Size)
10325 { # real size
10326 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10327 $Size = keys(%VTable);
10328 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010329 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010330 if(not $Size)
10331 { # shared library symbol size
10332 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10333 $Size /= $WORD_SIZE{$LibVersion};
10334 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010335 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010336 if(not $Size)
10337 { # model size
10338 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10339 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10340 }
10341 }
10342 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010343}
10344
10345sub isCopyingClass($$)
10346{
10347 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010348 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010349}
10350
10351sub isLeafClass($$)
10352{
10353 my ($ClassId, $LibVersion) = @_;
10354 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10355}
10356
10357sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010358{ # check structured type for public fields
10359 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010360}
10361
10362sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010363{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010364 my ($TypePtr, $Skip, $Start, $End) = @_;
10365 return 0 if(not $TypePtr);
10366 if($End==-1) {
10367 $End = keys(%{$TypePtr->{"Memb"}})-1;
10368 }
10369 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10370 {
10371 if($Skip and $Skip->{$MemPos})
10372 { # skip removed/added fields
10373 next;
10374 }
10375 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10376 {
10377 if(isPublic($TypePtr, $MemPos)) {
10378 return ($MemPos+1);
10379 }
10380 }
10381 }
10382 return 0;
10383}
10384
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010385sub isReserved($)
10386{ # reserved fields == private
10387 my $MName = $_[0];
10388 if($MName=~/reserved|padding|f_spare/i) {
10389 return 1;
10390 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010391 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010392 return 1;
10393 }
10394 if($MName=~/(pad\d+)/i) {
10395 return 1;
10396 }
10397 return 0;
10398}
10399
10400sub isPublic($$)
10401{
10402 my ($TypePtr, $FieldPos) = @_;
10403 return 0 if(not $TypePtr);
10404 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10405 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10406 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10407 { # by name in C language
10408 # FIXME: add other methods to detect private members
10409 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10410 if($MName=~/priv|abidata|parent_object/i)
10411 { # C-styled private data
10412 return 0;
10413 }
10414 if(lc($MName) eq "abi")
10415 { # ABI information/reserved field
10416 return 0;
10417 }
10418 if(isReserved($MName))
10419 { # reserved fields
10420 return 0;
10421 }
10422 return 1;
10423 }
10424 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10425 { # by access in C++ language
10426 return 1;
10427 }
10428 return 0;
10429}
10430
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010431sub getVTable_Real($$)
10432{
10433 my ($ClassName, $LibVersion) = @_;
10434 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10435 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010436 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010437 if(defined $Type{"VTable"}) {
10438 return %{$Type{"VTable"}};
10439 }
10440 }
10441 return ();
10442}
10443
10444sub cmpVTables($)
10445{
10446 my $ClassName = $_[0];
10447 my $Res = cmpVTables_Real($ClassName, 1);
10448 if($Res==-1) {
10449 $Res = cmpVTables_Model($ClassName);
10450 }
10451 return $Res;
10452}
10453
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010454sub cmpVTables_Model($)
10455{
10456 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010457 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010458 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010459 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010460 return 1;
10461 }
10462 }
10463 return 0;
10464}
10465
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010466sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010467{
10468 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010469 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10470 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010471 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010472 my %VTable_Old = getVTable_Real($ClassName, 1);
10473 my %VTable_New = getVTable_Real($ClassName, 2);
10474 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010475 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010476 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010477 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010478 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010479 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10480 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010481 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010482 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010483 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010484 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010485 my $Entry1 = $VTable_Old{$Offset};
10486 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010487 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010488 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010489 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010490 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010491
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010492 $Entry1 = simpleVEntry($Entry1);
10493 $Entry2 = simpleVEntry($Entry2);
10494 if($Entry1 ne $Entry2)
10495 { # register as changed
10496 if($Entry1=~/::([^:]+)\Z/)
10497 {
10498 my $M1 = $1;
10499 if($Entry2=~/::([^:]+)\Z/)
10500 {
10501 my $M2 = $1;
10502 if($M1 eq $M2)
10503 { # overridden
10504 next;
10505 }
10506 }
10507 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010508 if(differentDumps("G"))
10509 {
10510 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10511 {
10512 # GCC 4.6.1: -0x00000000000000010
10513 # GCC 4.7.0: -16
10514 next;
10515 }
10516 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010517 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010518 }
10519 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010520 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010521}
10522
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010523sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010524{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010525 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010526 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10527 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010528 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010529 { # already registered
10530 next;
10531 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010532 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010533 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010534 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010535 foreach my $Symbol (@Affected)
10536 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010537 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010538 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010539 "Target"=>$ClassName);
10540 }
10541 }
10542 }
10543}
10544
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010545sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010546{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010547 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010548 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010549 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010550 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010551 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010552 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010553 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010554 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010555 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010556 if($TName_Tid{1}{$ClassName}
10557 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010558 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010559 if(defined $CompleteSignature{1}{$Symbol}
10560 and $CompleteSignature{1}{$Symbol}{"Virt"})
10561 { # override some method in v.1
10562 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010563 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010564 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010565 }
10566 }
10567 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010568 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010569 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010570 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010571 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010572 if($TName_Tid{2}{$ClassName}
10573 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010574 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010575 if(defined $CompleteSignature{2}{$Symbol}
10576 and $CompleteSignature{2}{$Symbol}{"Virt"})
10577 { # override some method in v.2
10578 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010579 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010580 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010581 }
10582 }
10583 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010584 if($Level eq "Binary")
10585 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010586 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010587 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10588 { # check replacements, including pure virtual methods
10589 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10590 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010591 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010592 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10593 if($AddedPos==$RemovedPos)
10594 {
10595 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10596 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10597 last; # other methods will be reported as "added" or "removed"
10598 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010599 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010600 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10601 {
10602 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10603 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010604 next;
10605 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010606 my $ProblemType = "Virtual_Replacement";
10607 my @Affected = ($RemovedVFunc);
10608 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10609 { # pure methods
10610 if(not isUsedClass($ClassId, 1, $Level))
10611 { # not a parameter of some exported method
10612 next;
10613 }
10614 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010615
10616 # affected all methods (both virtual and non-virtual ones)
10617 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10618 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010619 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010620 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010621 foreach my $AffectedInt (@Affected)
10622 {
10623 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10624 { # affected exported methods only
10625 next;
10626 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010627 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10628 next;
10629 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010630 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10631 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010632 "Target"=>get_Signature($AddedVFunc, 2),
10633 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10634 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010635 }
10636 }
10637 }
10638 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010639 if(not checkDump(1, "2.0")
10640 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010641 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010642 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010643 return;
10644 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010645 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010646 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010647 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010648 next if(not $ClassId_Old);
10649 if(not isCreatable($ClassId_Old, 1))
10650 { # skip classes without public constructors (including auto-generated)
10651 # example: class has only a private exported or private inline constructor
10652 next;
10653 }
10654 if($ClassName=~/>/)
10655 { # skip affected template instances
10656 next;
10657 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010658 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010659 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010660 if(not $ClassId_New) {
10661 next;
10662 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010663 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010664 if($Class_New{"Type"}!~/Class|Struct/)
10665 { # became typedef
10666 if($Level eq "Binary") {
10667 next;
10668 }
10669 if($Level eq "Source")
10670 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010671 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010672 if($Class_New{"Type"}!~/Class|Struct/) {
10673 next;
10674 }
10675 $ClassId_New = $Class_New{"Tid"};
10676 }
10677 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010678
10679 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10680 { # incomplete info in the ABI dump
10681 next;
10682 }
10683
10684
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010685 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10686 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 +040010687
10688 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10689 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10690
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010691 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010692 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10693 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010694 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10695 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010696 my $Shift_Old = getShift($ClassId_Old, 1);
10697 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010698 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010699 my ($Added, $Removed) = (0, 0);
10700 my @StableBases_Old = ();
10701 foreach my $BaseId (@Bases_Old)
10702 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010703 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010704 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010705 push(@StableBases_Old, $BaseId);
10706 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010707 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010708 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010709 { # removed base
10710 # excluding namespace::SomeClass to SomeClass renaming
10711 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010712 if($Level eq "Binary")
10713 { # Binary-level
10714 if($Shift_Old ne $Shift_New)
10715 { # affected fields
10716 if(havePubFields(\%Class_Old)) {
10717 $ProblemKind .= "_And_Shift";
10718 }
10719 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10720 $ProblemKind .= "_And_Size";
10721 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010722 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010723 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10724 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010725 { # affected v-table
10726 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010727 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010728 }
10729 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010730 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010731 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10732 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010733 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10734 {
10735 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10736 if($ProblemKind=~/VTable/) {
10737 $VTableChanged_M{$SubName}=1;
10738 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010739 }
10740 }
10741 foreach my $Interface (@Affected)
10742 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010743 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10744 next;
10745 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010746 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010747 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010748 "Target"=>$BaseName,
10749 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10750 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10751 "Shift"=>abs($Shift_New-$Shift_Old) );
10752 }
10753 $Removed+=1;
10754 }
10755 }
10756 my @StableBases_New = ();
10757 foreach my $BaseId (@Bases_New)
10758 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010759 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010760 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010761 push(@StableBases_New, $BaseId);
10762 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010763 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010764 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010765 { # added base
10766 # excluding namespace::SomeClass to SomeClass renaming
10767 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010768 if($Level eq "Binary")
10769 { # Binary-level
10770 if($Shift_Old ne $Shift_New)
10771 { # affected fields
10772 if(havePubFields(\%Class_Old)) {
10773 $ProblemKind .= "_And_Shift";
10774 }
10775 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10776 $ProblemKind .= "_And_Size";
10777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010778 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010779 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10780 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010781 { # affected v-table
10782 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010783 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010784 }
10785 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010786 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010787 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10788 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010789 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10790 {
10791 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10792 if($ProblemKind=~/VTable/) {
10793 $VTableChanged_M{$SubName}=1;
10794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010795 }
10796 }
10797 foreach my $Interface (@Affected)
10798 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010799 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10800 next;
10801 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010802 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010803 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010804 "Target"=>$BaseName,
10805 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10806 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10807 "Shift"=>abs($Shift_New-$Shift_Old) );
10808 }
10809 $Added+=1;
10810 }
10811 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010812 if($Level eq "Binary")
10813 { # Binary-level
10814 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010815 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10816 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010817 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010818 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010819 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010820 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010821 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010822 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10823 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010824 if($NewPos!=$OldPos)
10825 { # changed position of the base class
10826 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010827 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010828 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10829 next;
10830 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010831 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10832 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010833 "Target"=>$BaseName,
10834 "Old_Value"=>$OldPos-1,
10835 "New_Value"=>$NewPos-1 );
10836 }
10837 }
10838 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10839 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10840 { # became non-virtual base
10841 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10842 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010843 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10844 next;
10845 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010846 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10847 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010848 "Target"=>$BaseName );
10849 }
10850 }
10851 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10852 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10853 { # became virtual base
10854 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10855 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010856 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10857 next;
10858 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010859 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10860 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010861 "Target"=>$BaseName );
10862 }
10863 }
10864 }
10865 }
10866 # detect size changes in base classes
10867 if($Shift_Old!=$Shift_New)
10868 { # size of allocable class
10869 foreach my $BaseId (@StableBases_Old)
10870 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010871 my %BaseType = get_Type($BaseId, 1);
10872 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010873 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010874 if($Size_Old ne $Size_New
10875 and $Size_Old and $Size_New)
10876 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010877 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010878 if(isCopyingClass($BaseId, 1)) {
10879 $ProblemType = "Size_Of_Copying_Class";
10880 }
10881 elsif($AllocableClass{1}{$BaseType{"Name"}})
10882 {
10883 if($Size_New>$Size_Old)
10884 { # increased size
10885 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010886 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010887 else
10888 { # decreased size
10889 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10890 if(not havePubFields(\%Class_Old))
10891 { # affected class has no public members
10892 next;
10893 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010894 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010895 }
10896 next if(not $ProblemType);
10897 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10898 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010899 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10900 next;
10901 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010902 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10903 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010904 "Target"=>$BaseType{"Name"},
10905 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10906 "New_Size"=>$Size_New*$BYTE_SIZE );
10907 }
10908 }
10909 }
10910 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010911 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010912 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010913 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010914 { # compare virtual tables size in base classes
10915 my $VShift_Old = getVShift($ClassId_Old, 1);
10916 my $VShift_New = getVShift($ClassId_New, 2);
10917 if($VShift_Old ne $VShift_New)
10918 { # changes in the base class or changes in the list of base classes
10919 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10920 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10921 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010922 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010923 foreach my $BaseId (@AllBases_Old)
10924 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010925 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010926 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010927 { # lost base
10928 next;
10929 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010930 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10931 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010932 if($VSize_Old!=$VSize_New)
10933 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010934 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010935 { # TODO: affected non-virtual methods?
10936 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010937 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10938 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010939 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010940 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010941 { # skip interfaces that have not changed the absolute virtual position
10942 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010943 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010944 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10945 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010946 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010947 $VTableChanged_M{$BaseType{"Name"}} = 1;
10948 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010949 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10950 { # the reason of the layout change: added virtual functions
10951 next if($VirtualReplacement{$VirtFunc});
10952 my $ProblemType = "Added_Virtual_Method";
10953 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10954 $ProblemType = "Added_Pure_Virtual_Method";
10955 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010956 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010957 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010958 "Target"=>get_Signature($VirtFunc, 2) );
10959 }
10960 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10961 { # the reason of the layout change: removed virtual functions
10962 next if($VirtualReplacement{$VirtFunc});
10963 my $ProblemType = "Removed_Virtual_Method";
10964 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10965 $ProblemType = "Removed_Pure_Virtual_Method";
10966 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010967 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010968 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010969 "Target"=>get_Signature($VirtFunc, 1) );
10970 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010971 }
10972 }
10973 }
10974 }
10975 }
10976 }
10977 }
10978}
10979
10980sub isCreatable($$)
10981{
10982 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010983 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010984 or isCopyingClass($ClassId, $LibVersion)) {
10985 return 1;
10986 }
10987 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10988 { # Fix for incomplete data: if this class has
10989 # a base class then it should also has a constructor
10990 return 1;
10991 }
10992 if($ReturnedClass{$LibVersion}{$ClassId})
10993 { # returned by some method of this class
10994 # or any other class
10995 return 1;
10996 }
10997 return 0;
10998}
10999
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011000sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011001{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011002 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011003 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11004 { # parameter of some exported method
11005 return 1;
11006 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011007 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11008 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011009 { # method from target class
11010 return 1;
11011 }
11012 return 0;
11013}
11014
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011015sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011016{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011017 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011018 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011019 # - virtual
11020 # - pure-virtual
11021 # - non-virtual
11022 if($CompleteSignature{1}{$Interface}{"Data"})
11023 { # global data is not affected
11024 return;
11025 }
11026 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011027 if(not $Class_Id) {
11028 return;
11029 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011030 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011031 if(cmpVTables_Real($CName, 1)==0)
11032 { # no changes
11033 return;
11034 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011035 $CheckedTypes{$Level}{$CName} = 1;
11036 if($Level eq "Binary")
11037 { # Binary-level
11038 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11039 and not isUsedClass($Class_Id, 1, $Level))
11040 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011041 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011042 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011043 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011044 }
11045 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11046 {
11047 if(defined $VirtualTable{2}{$CName}{$Func}
11048 and defined $CompleteSignature{2}{$Func})
11049 {
11050 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11051 and $CompleteSignature{2}{$Func}{"PureVirt"})
11052 { # became pure virtual
11053 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11054 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011055 "Target"=>get_Signature_M($Func, 1) );
11056 $VTableChanged_M{$CName} = 1;
11057 }
11058 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11059 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11060 { # became non-pure virtual
11061 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11062 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011063 "Target"=>get_Signature_M($Func, 1) );
11064 $VTableChanged_M{$CName} = 1;
11065 }
11066 }
11067 }
11068 if($Level eq "Binary")
11069 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011070 # check virtual table structure
11071 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11072 {
11073 next if($Interface eq $AddedVFunc);
11074 next if($VirtualReplacement{$AddedVFunc});
11075 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11076 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11077 { # pure virtual methods affect all others (virtual and non-virtual)
11078 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011079 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011080 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011081 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011082 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011083 elsif(not defined $VirtualTable{1}{$CName}
11084 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011085 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011086 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011087 { # became polymorphous class, added v-table pointer
11088 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011089 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011090 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011091 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011092 }
11093 else
11094 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011095 my $VSize_Old = getVTable_Size($CName, 1);
11096 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011097 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011098 if(isCopyingClass($Class_Id, 1))
11099 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11100 my $ProblemType = "Added_Virtual_Method";
11101 if(isLeafClass($Class_Id, 1)) {
11102 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11103 }
11104 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11105 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011106 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011107 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011108 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011109 else
11110 {
11111 my $ProblemType = "Added_Virtual_Method";
11112 if(isLeafClass($Class_Id, 1)) {
11113 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11114 }
11115 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11116 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011117 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011118 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011119 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011120 }
11121 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011122 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11123 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011124 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011125 if(defined $VirtualTable{1}{$CName}
11126 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011127 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011128 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11129 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011130
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011131 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011132 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011133 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11134 foreach my $ASymbol (@Affected)
11135 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011136 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11137 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011138 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011139 next;
11140 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011141 }
11142 $CheckedSymbols{$Level}{$ASymbol} = 1;
11143 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11144 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011145 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011146 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011147 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011148 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011149 }
11150 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011151 else {
11152 # safe
11153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011154 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011155 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11156 {
11157 next if($VirtualReplacement{$RemovedVFunc});
11158 if($RemovedVFunc eq $Interface
11159 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11160 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011161 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011162 next;
11163 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011164 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011165 { # became non-polymorphous class, removed v-table pointer
11166 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11167 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011168 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011169 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011170 }
11171 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11172 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11173 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011174 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011175 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011176 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11177 next;
11178 }
11179 my $VPos_New = -1;
11180 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011181 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011182 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11183 }
11184 else
11185 {
11186 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011187 next;
11188 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011189 }
11190 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11191 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11192 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11193 {
11194 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11195 foreach my $ASymbol (@Affected)
11196 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011197 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11198 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011199 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011200 next;
11201 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011202 }
11203 my $ProblemType = "Removed_Virtual_Method";
11204 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11205 $ProblemType = "Removed_Pure_Virtual_Method";
11206 }
11207 $CheckedSymbols{$Level}{$ASymbol} = 1;
11208 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11209 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011210 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011211 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011212 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011213 }
11214 }
11215 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011216 }
11217 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011218 else
11219 { # Source-level
11220 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011221 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011222 next if($Interface eq $AddedVFunc);
11223 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011224 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011225 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11226 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011227 "Target"=>get_Signature($AddedVFunc, 2) );
11228 }
11229 }
11230 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11231 {
11232 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11233 {
11234 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11235 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011236 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011237 }
11238 }
11239 }
11240}
11241
11242sub find_MemberPair_Pos_byName($$)
11243{
11244 my ($Member_Name, $Pair_Type) = @_;
11245 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11246 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11247 {
11248 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11249 {
11250 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11251 $Name=~s/\A[_]+|[_]+\Z//g;
11252 if($Name eq $Member_Name) {
11253 return $MemberPair_Pos;
11254 }
11255 }
11256 }
11257 return "lost";
11258}
11259
11260sub find_MemberPair_Pos_byVal($$)
11261{
11262 my ($Member_Value, $Pair_Type) = @_;
11263 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11264 {
11265 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11266 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11267 return $MemberPair_Pos;
11268 }
11269 }
11270 return "lost";
11271}
11272
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011273sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011274{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011275 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011276 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011277 if( $_->{"T1"} eq $_[0]
11278 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011279 {
11280 return 1;
11281 }
11282 }
11283 return 0;
11284}
11285
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011286sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011287{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011288 my %IDs = (
11289 "T1" => $_[0],
11290 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011291 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011292 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011293}
11294
11295sub isRenamed($$$$$)
11296{
11297 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11298 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11299 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011300 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011301 if(not defined $Type2->{"Memb"}{$MemPos}) {
11302 return "";
11303 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011304 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011305 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011306
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011307 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11308 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011309 if($MemberPair_Pos_Rev eq "lost")
11310 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011311 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11312 { # base type match
11313 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011314 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011315 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11316 { # exact type match
11317 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011318 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011319 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11320 { # size match
11321 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011322 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011323 if(isReserved($Pair_Name))
11324 { # reserved fields
11325 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011326 }
11327 }
11328 return "";
11329}
11330
11331sub isLastElem($$)
11332{
11333 my ($Pos, $TypeRef) = @_;
11334 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11335 if($Name=~/last|count|max|total/i)
11336 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11337 return 1;
11338 }
11339 elsif($Name=~/END|NLIMITS\Z/)
11340 { # __RLIMIT_NLIMITS
11341 return 1;
11342 }
11343 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11344 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11345 { # NImageFormats, NColorRoles
11346 return 1;
11347 }
11348 return 0;
11349}
11350
11351sub nonComparable($$)
11352{
11353 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011354
11355 my $N1 = $T1->{"Name"};
11356 my $N2 = $T2->{"Name"};
11357
11358 $N1=~s/\A(struct|union|enum) //;
11359 $N2=~s/\A(struct|union|enum) //;
11360
11361 if($N1 ne $N2
11362 and not isAnon($N1)
11363 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011364 { # different names
11365 if($T1->{"Type"} ne "Pointer"
11366 or $T2->{"Type"} ne "Pointer")
11367 { # compare base types
11368 return 1;
11369 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011370 if($N1!~/\Avoid\s*\*/
11371 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011372 {
11373 return 1;
11374 }
11375 }
11376 elsif($T1->{"Type"} ne $T2->{"Type"})
11377 { # different types
11378 if($T1->{"Type"} eq "Class"
11379 and $T2->{"Type"} eq "Struct")
11380 { # "class" to "struct"
11381 return 0;
11382 }
11383 elsif($T2->{"Type"} eq "Class"
11384 and $T1->{"Type"} eq "Struct")
11385 { # "struct" to "class"
11386 return 0;
11387 }
11388 else
11389 { # "class" to "enum"
11390 # "union" to "class"
11391 # ...
11392 return 1;
11393 }
11394 }
11395 return 0;
11396}
11397
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011398sub isOpaque($)
11399{
11400 my $T = $_[0];
11401 if(not defined $T->{"Memb"})
11402 {
11403 return 1;
11404 }
11405 return 0;
11406}
11407
11408sub removeVPtr($)
11409{ # support for old ABI dumps
11410 my $TPtr = $_[0];
11411 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11412 if($#Pos>=1)
11413 {
11414 foreach my $Pos (0 .. $#Pos-1)
11415 {
11416 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11417 }
11418 delete($TPtr->{"Memb"}{$#Pos});
11419 }
11420}
11421
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011422sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011423{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011424 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011425 return {} if(not $Type1_Id or not $Type2_Id);
11426
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011427 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011428 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011429 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011430 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011431
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011432 my %Type1 = get_Type($Type1_Id, 1);
11433 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011434 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011435 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011436 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011437
11438 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011439 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11440 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011441
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011442 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11443
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011444 my %SubProblems = ();
11445
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011446 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11447 {
11448 if($Type1_Pure{"Type"}=~/Struct|Union/
11449 and $Type2_Pure{"Type"}=~/Struct|Union/)
11450 {
11451 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11452 {
11453 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11454 "Target"=>$Type1_Pure{"Name"},
11455 "Type_Name"=>$Type1_Pure{"Name"} );
11456
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011457 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011458 }
11459 }
11460 }
11461
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011462 if(not $Type1_Pure{"Size"}
11463 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011464 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011465 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11466 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11467 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011468 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011469 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011470 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011471 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011472 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011473 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011474 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011475 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11476 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11477 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011478
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011479 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11480 { # support for old ABI dumps
11481 # _vptr field added in 3.0
11482 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11483 {
11484 if(defined $Type2_Pure{"Memb"}
11485 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11486 {
11487 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11488 delete($Type2_Pure{"Memb"}{0});
11489 }
11490 else {
11491 removeVPtr(\%Type2_Pure);
11492 }
11493 }
11494 }
11495 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11496 {
11497 if(defined $Type1_Pure{"Memb"}
11498 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11499 {
11500 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11501 delete($Type1_Pure{"Memb"}{0});
11502 }
11503 else {
11504 removeVPtr(\%Type1_Pure);
11505 }
11506 }
11507 }
11508 }
11509
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011510 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11511 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011512
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011513 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011514 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11515 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011516 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011517 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11518 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011519 if($Base_1{"Name"} ne $Base_2{"Name"})
11520 {
11521 if(differentDumps("G")
11522 or differentDumps("V"))
11523 { # different GCC versions or different dumps
11524 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11525 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11526 # std::__va_list and __va_list
11527 $Base_1{"Name"}=~s/\A(\w+::)+//;
11528 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011529 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11530 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011531 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011532 }
11533 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11534 and $Base_1{"Name"} ne $Base_2{"Name"})
11535 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011536 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011537 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011538 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011539 {
11540 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11541 "Target"=>$Typedef_1{"Name"},
11542 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011543 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11544 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11545 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011546 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11547 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011548 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011549 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011550 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11551 {
11552 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11553 "Target"=>$Typedef_1{"Name"},
11554 "Type_Name"=>$Typedef_1{"Name"},
11555 "Old_Value"=>$Base_1{"Name"},
11556 "New_Value"=>$Base_2{"Name"} );
11557 }
11558 else
11559 {
11560 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11561 "Target"=>$Typedef_1{"Name"},
11562 "Type_Name"=>$Typedef_1{"Name"},
11563 "Old_Value"=>$Base_1{"Name"},
11564 "New_Value"=>$Base_2{"Name"} );
11565 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011566 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011567 }
11568 }
11569 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11570 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011571 my $TT1 = $Type1_Pure{"Type"};
11572 my $TT2 = $Type2_Pure{"Type"};
11573
11574 if($TT1 ne $TT2
11575 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011576 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011577 my $Short1 = $Type1_Pure{"Name"};
11578 my $Short2 = $Type2_Pure{"Name"};
11579
11580 $Short1=~s/\A\Q$TT1\E //ig;
11581 $Short2=~s/\A\Q$TT2\E //ig;
11582
11583 if($Short1 eq $Short2)
11584 {
11585 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11586 "Target"=>$Type1_Pure{"Name"},
11587 "Type_Name"=>$Type1_Pure{"Name"},
11588 "Old_Value"=>lc($Type1_Pure{"Type"}),
11589 "New_Value"=>lc($Type2_Pure{"Type"}) );
11590 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011591 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011592 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011593 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011594 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011595 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11596 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11597 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11598 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011599 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011600 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011601 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011602 {
11603 my $ProblemKind = "DataType_Size";
11604 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011605 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011606 {
11607 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11608 $ProblemKind = "Size_Of_Copying_Class";
11609 }
11610 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11611 {
11612 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11613 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11614 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011615 else
11616 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011617 # descreased size of allocable class
11618 # it has no special effects
11619 }
11620 }
11621 }
11622 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11623 "Target"=>$Type1_Pure{"Name"},
11624 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011625 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011626 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011627 }
11628 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011629 if(defined $Type1_Pure{"BaseType"}
11630 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011631 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011632 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11633 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011634 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011635 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11636 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011637 }
11638 }
11639 }
11640 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11641 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11642 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11643 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11644 { # detect removed and renamed fields
11645 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11646 next if(not $Member_Name);
11647 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);
11648 if($MemberPair_Pos eq "lost")
11649 {
11650 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11651 {
11652 if(isUnnamed($Member_Name))
11653 { # support for old-version dumps
11654 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011655 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011656 next;
11657 }
11658 }
11659 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11660 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011661 $RenamedField{$Member_Pos} = $RenamedTo;
11662 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011663 }
11664 else
11665 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011666 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011667 }
11668 }
11669 elsif($Type1_Pure{"Type"} eq "Enum")
11670 {
11671 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11672 next if($Member_Value1 eq "");
11673 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11674 if($MemberPair_Pos ne "lost")
11675 { # renamed
11676 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11677 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11678 if($MemberPair_Pos_Rev eq "lost")
11679 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011680 $RenamedField{$Member_Pos} = $RenamedTo;
11681 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011682 }
11683 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011684 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011685 }
11686 }
11687 else
11688 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011689 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011690 }
11691 }
11692 }
11693 else
11694 { # related
11695 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11696 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11697 }
11698 }
11699 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11700 { # detect added fields
11701 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11702 next if(not $Member_Name);
11703 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);
11704 if($MemberPair_Pos eq "lost")
11705 {
11706 if(isUnnamed($Member_Name))
11707 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011708 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011709 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011710 next;
11711 }
11712 }
11713 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11714 {
11715 if(not $RenamedField_Rev{$Member_Pos})
11716 { # added
11717 $AddedField{$Member_Pos}=1;
11718 }
11719 }
11720 }
11721 }
11722 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11723 { # detect moved fields
11724 my (%RelPos, %RelPosName, %AbsPos) = ();
11725 my $Pos = 0;
11726 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11727 { # relative positions in 1st version
11728 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11729 next if(not $Member_Name);
11730 if(not $RemovedField{$Member_Pos})
11731 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011732 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011733 $RelPosName{1}{$Pos} = $Member_Name;
11734 $AbsPos{1}{$Pos++} = $Member_Pos;
11735 }
11736 }
11737 $Pos = 0;
11738 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11739 { # relative positions in 2nd version
11740 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11741 next if(not $Member_Name);
11742 if(not $AddedField{$Member_Pos})
11743 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011744 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011745 $RelPosName{2}{$Pos} = $Member_Name;
11746 $AbsPos{2}{$Pos++} = $Member_Pos;
11747 }
11748 }
11749 foreach my $Member_Name (keys(%{$RelPos{1}}))
11750 {
11751 my $RPos1 = $RelPos{1}{$Member_Name};
11752 my $AbsPos1 = $NameToPosA{$Member_Name};
11753 my $Member_Name2 = $Member_Name;
11754 if(my $RenamedTo = $RenamedField{$AbsPos1})
11755 { # renamed
11756 $Member_Name2 = $RenamedTo;
11757 }
11758 my $RPos2 = $RelPos{2}{$Member_Name2};
11759 if($RPos2 ne "" and $RPos1 ne $RPos2)
11760 { # different relative positions
11761 my $AbsPos2 = $NameToPosB{$Member_Name2};
11762 if($AbsPos1 ne $AbsPos2)
11763 { # different absolute positions
11764 my $ProblemType = "Moved_Field";
11765 if(not isPublic(\%Type1_Pure, $AbsPos1))
11766 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011767 if($Level eq "Source") {
11768 next;
11769 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011770 $ProblemType = "Moved_Private_Field";
11771 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011772 if($Level eq "Binary"
11773 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011774 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011775 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011776 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011777 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011778 if($MemSize1 ne $MemSize2) {
11779 $ProblemType .= "_And_Size";
11780 }
11781 }
11782 if($ProblemType eq "Moved_Private_Field") {
11783 next;
11784 }
11785 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11786 "Target"=>$Member_Name,
11787 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011788 "Old_Value"=>$RPos1,
11789 "New_Value"=>$RPos2 );
11790 }
11791 }
11792 }
11793 }
11794 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011795 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011796 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11797 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011798 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011799 if(my $RenamedTo = $RenamedField{$Member_Pos})
11800 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011801 if(defined $Constants{2}{$Member_Name})
11802 {
11803 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11804 { # define OLD NEW
11805 next; # Safe
11806 }
11807 }
11808
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011809 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11810 {
11811 if(isPublic(\%Type1_Pure, $Member_Pos))
11812 {
11813 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11814 "Target"=>$Member_Name,
11815 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011816 "Old_Value"=>$Member_Name,
11817 "New_Value"=>$RenamedTo );
11818 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011819 elsif(isReserved($Member_Name))
11820 {
11821 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11822 "Target"=>$Member_Name,
11823 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011824 "Old_Value"=>$Member_Name,
11825 "New_Value"=>$RenamedTo );
11826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011827 }
11828 elsif($Type1_Pure{"Type"} eq "Enum")
11829 {
11830 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11831 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11832 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011833 "Old_Value"=>$Member_Name,
11834 "New_Value"=>$RenamedTo );
11835 }
11836 }
11837 elsif($RemovedField{$Member_Pos})
11838 { # removed
11839 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11840 {
11841 my $ProblemType = "Removed_Field";
11842 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011843 or isUnnamed($Member_Name))
11844 {
11845 if($Level eq "Source") {
11846 next;
11847 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011848 $ProblemType = "Removed_Private_Field";
11849 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011850 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011851 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011852 {
11853 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11854 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011855 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 +040011856 { # changed offset
11857 $ProblemType .= "_And_Layout";
11858 }
11859 }
11860 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11861 { # affected size
11862 $ProblemType .= "_And_Size";
11863 }
11864 }
11865 if($ProblemType eq "Removed_Private_Field") {
11866 next;
11867 }
11868 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11869 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011870 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011871 }
11872 elsif($Type2_Pure{"Type"} eq "Union")
11873 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011874 if($Level eq "Binary"
11875 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011876 {
11877 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11878 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011879 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011880 }
11881 else
11882 {
11883 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11884 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011885 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011886 }
11887 }
11888 elsif($Type1_Pure{"Type"} eq "Enum")
11889 {
11890 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11891 "Target"=>$Member_Name,
11892 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011893 "Old_Value"=>$Member_Name );
11894 }
11895 }
11896 else
11897 { # changed
11898 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11899 if($Type1_Pure{"Type"} eq "Enum")
11900 {
11901 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11902 next if($Member_Value1 eq "");
11903 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11904 next if($Member_Value2 eq "");
11905 if($Member_Value1 ne $Member_Value2)
11906 {
11907 my $ProblemType = "Enum_Member_Value";
11908 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11909 $ProblemType = "Enum_Last_Member_Value";
11910 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011911 if($SkipConstants{1}{$Member_Name}) {
11912 $ProblemType = "Enum_Private_Member_Value";
11913 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011914 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11915 "Target"=>$Member_Name,
11916 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011917 "Old_Value"=>$Member_Value1,
11918 "New_Value"=>$Member_Value2 );
11919 }
11920 }
11921 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11922 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011923 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11924 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11925
11926 if($Access1 ne "private"
11927 and $Access2 eq "private")
11928 {
11929 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11930 "Target"=>$Member_Name,
11931 "Type_Name"=>$Type1_Pure{"Name"});
11932 }
11933 elsif($Access1 ne "protected"
11934 and $Access1 ne "private"
11935 and $Access2 eq "protected")
11936 {
11937 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11938 "Target"=>$Member_Name,
11939 "Type_Name"=>$Type1_Pure{"Name"});
11940 }
11941
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011942 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11943 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011944 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011945 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
11946 $SizeV1 = $BSize1;
11947 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011948 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011949 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
11950 $SizeV2 = $BSize2;
11951 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011952 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
11953 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011954 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011955 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011956 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011957 {
11958 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
11959 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
11960 { # field size change (including anon-structures and unions)
11961 # - same types
11962 # - unnamed types
11963 # - bitfields
11964 my $ProblemType = "Field_Size";
11965 if(not isPublic(\%Type1_Pure, $Member_Pos)
11966 or isUnnamed($Member_Name))
11967 { # should not be accessed by applications, goes to "Low Severity"
11968 # example: "abidata" members in GStreamer types
11969 $ProblemType = "Private_".$ProblemType;
11970 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011971 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 +040011972 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011973 if($Type2_Pure{"Type"} ne "Union"
11974 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011975 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011976 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 +040011977 { # changed offset
11978 $ProblemType .= "_And_Layout";
11979 }
11980 }
11981 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11982 $ProblemType .= "_And_Type_Size";
11983 }
11984 }
11985 if($ProblemType eq "Private_Field_Size")
11986 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011987 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040011988 if($ProblemType eq "Field_Size")
11989 {
11990 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
11991 { # Low severity
11992 $ProblemType = "Struct_Field_Size_Increased";
11993 }
11994 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011995 if($ProblemType)
11996 { # register a problem
11997 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11998 "Target"=>$Member_Name,
11999 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012000 "Old_Size"=>$SizeV1,
12001 "New_Size"=>$SizeV2);
12002 }
12003 }
12004 }
12005 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12006 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12007 { # do NOT check bitfield type changes
12008 next;
12009 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012010 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012011 {
12012 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12013 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12014 {
12015 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12016 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012017 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012018 }
12019 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12020 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12021 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012022 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012023 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012024 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012025 }
12026 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012027 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12028 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012029 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012030 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12031 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012032
12033 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012034 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012035 or $ProblemType eq "Field_Type_And_Size"
12036 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012037 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012038 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012039 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012040 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012041 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012042 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012043 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012044 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012045 }
12046 }
12047 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12048 {
12049 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012050 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012051 }
12052 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012053 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012054 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012055 }
12056 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12057 {
12058 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012059 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012060 }
12061 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012062 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012063 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012064 }
12065 }
12066 }
12067
12068 if($Level eq "Source")
12069 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012070 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012071 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012072 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12073 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012074
12075 if($ProblemType eq "Field_Type")
12076 {
12077 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012078 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012079 }
12080 }
12081 }
12082 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012083
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012084 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012085 {
12086 my $ProblemType_Init = $ProblemType;
12087 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012088 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012089 if(not isPublic(\%Type1_Pure, $Member_Pos)
12090 or isUnnamed($Member_Name)) {
12091 $ProblemType = "Private_".$ProblemType;
12092 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012093 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 +040012094 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012095 if($Type2_Pure{"Type"} ne "Union"
12096 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012097 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012098 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 +040012099 { # changed offset
12100 $ProblemType .= "_And_Layout";
12101 }
12102 }
12103 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12104 $ProblemType .= "_And_Type_Size";
12105 }
12106 }
12107 }
12108 else
12109 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012110 # TODO: Private_Field_Type rule?
12111
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012112 if(not isPublic(\%Type1_Pure, $Member_Pos)
12113 or isUnnamed($Member_Name)) {
12114 next;
12115 }
12116 }
12117 if($ProblemType eq "Private_Field_Type_And_Size")
12118 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012119 }
12120 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12121 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012122 "Type_Name"=>$Type1_Pure{"Name"});
12123
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012124 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012125 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012126 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012127 }
12128 }
12129 if(not isPublic(\%Type1_Pure, $Member_Pos))
12130 { # do NOT check internal type changes
12131 next;
12132 }
12133 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012134 { # checking member type changes
12135 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12136
12137 my %DupProblems = ();
12138
12139 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012140 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012141 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012142 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012143 if(not defined $AllAffected)
12144 {
12145 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12146 next;
12147 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012148 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012149
12150 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12151 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12152
12153 if(not defined $AllAffected)
12154 {
12155 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012156 }
12157 }
12158 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012159
12160 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012161 }
12162 }
12163 }
12164 }
12165 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12166 { # checking added members, public and private
12167 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12168 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012169 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012170 if($AddedField{$Member_Pos})
12171 { # added
12172 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12173 {
12174 my $ProblemType = "Added_Field";
12175 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012176 or isUnnamed($Member_Name))
12177 {
12178 if($Level eq "Source") {
12179 next;
12180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012181 $ProblemType = "Added_Private_Field";
12182 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012183 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012184 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012185 {
12186 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12187 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012188 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 +040012189 { # changed offset
12190 $ProblemType .= "_And_Layout";
12191 }
12192 }
12193 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12194 $ProblemType .= "_And_Size";
12195 }
12196 }
12197 if($ProblemType eq "Added_Private_Field")
12198 { # skip added private fields
12199 next;
12200 }
12201 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12202 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012203 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012204 }
12205 elsif($Type2_Pure{"Type"} eq "Union")
12206 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012207 if($Level eq "Binary"
12208 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012209 {
12210 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12211 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012212 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012213 }
12214 else
12215 {
12216 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12217 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012218 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012219 }
12220 }
12221 elsif($Type2_Pure{"Type"} eq "Enum")
12222 {
12223 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12224 next if($Member_Value eq "");
12225 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12226 "Target"=>$Member_Name,
12227 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012228 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012229 }
12230 }
12231 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012232
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012233 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012234 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012235}
12236
12237sub isUnnamed($) {
12238 return $_[0]=~/\Aunnamed\d+\Z/;
12239}
12240
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012241sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012242{
12243 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012244 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12245 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12246 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12247 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012248 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012249 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012250 }
12251 return $TypeName;
12252}
12253
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012254sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012255{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012256 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012257 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012258 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12259 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012260 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012261 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12262 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012263 return () if(not $Type{"Type"});
12264 if($Type{"Type"} ne $Type_Type)
12265 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012266 return () if(not $Type{"BaseType"});
12267 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012268 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012269 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012270 return %Type;
12271}
12272
12273my %TypeSpecAttributes = (
12274 "Const" => 1,
12275 "Volatile" => 1,
12276 "ConstVolatile" => 1,
12277 "Restrict" => 1,
12278 "Typedef" => 1
12279);
12280
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012281sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012282{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012283 my ($TypeId, $Info) = @_;
12284 if(not $TypeId or not $Info
12285 or not $Info->{$TypeId}) {
12286 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012287 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012288 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12289 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12290 }
12291 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012292 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012293 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012294 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012295 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012296 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012297 return %Type;
12298}
12299
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012300sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012301{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012302 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012303 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012304 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12305 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012306 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012307 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12308 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012309 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12310 my $PLevel = 0;
12311 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12312 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012313 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012314 return $PLevel if(not $Type{"BaseType"});
12315 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12316 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12317 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012318}
12319
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012320sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012321{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012322 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012323 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012324 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12325 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012326 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012327 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12328 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012329 return %Type if(not $Type{"BaseType"});
12330 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012331 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012332 return %Type;
12333}
12334
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012335sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012336{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012337 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012338 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012339 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12340 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012341 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012342 my $Qual = "";
12343 if($Type{"Type"} eq "Pointer") {
12344 $Qual .= "*";
12345 }
12346 elsif($Type{"Type"} eq "Ref") {
12347 $Qual .= "&";
12348 }
12349 elsif($Type{"Type"} eq "ConstVolatile") {
12350 $Qual .= "const volatile";
12351 }
12352 elsif($Type{"Type"} eq "Const"
12353 or $Type{"Type"} eq "Volatile"
12354 or $Type{"Type"} eq "Restrict") {
12355 $Qual .= lc($Type{"Type"});
12356 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012357 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012358 return $BQual.$Qual;
12359}
12360
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012361sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012362{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012363 my ($TypeId, $Info) = @_;
12364 if(not $TypeId or not $Info
12365 or not $Info->{$TypeId}) {
12366 return ();
12367 }
12368 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012369 return %Type if(not $Type{"BaseType"});
12370 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012371 {
12372 if($Info->{$BTid}) {
12373 return %{$Info->{$BTid}};
12374 }
12375 else { # something is going wrong
12376 return ();
12377 }
12378 }
12379 else {
12380 return %Type;
12381 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012382}
12383
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012384sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012385{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012386 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012387 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012388 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12389 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012390}
12391
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012392sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012393{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012394 my $Symbol = $_[0];
12395 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12396}
12397
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012398sub isInLineInst($$$) {
12399 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12400}
12401
12402sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012403{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012404 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012405 if($CheckObjectsOnly)
12406 {
12407 if($Symbol!~/\A(_Z|\?)/) {
12408 return 0;
12409 }
12410 if(my $Signature = $tr_name{$Symbol})
12411 {
12412 if(index($Signature,">")==-1) {
12413 return 0;
12414 }
12415 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
12416 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012417 if(index($ShortName,"<")!=-1
12418 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012419 return 1;
12420 }
12421 }
12422 }
12423 }
12424 else
12425 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012426 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012427 {
12428 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
12429 {
12430 if(index($ClassName,"<")!=-1) {
12431 return 1;
12432 }
12433 }
12434 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012435 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012436 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012437 if(index($ShortName,"<")!=-1
12438 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012439 return 1;
12440 }
12441 }
12442 }
12443 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012444}
12445
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012446sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012447{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012448 my ($Symbol, $SInfo, $LibVersion) = @_;
12449 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012450 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012451 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012452 { # class specialization
12453 return 1;
12454 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012455 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012456 { # method specialization
12457 return 1;
12458 }
12459 }
12460 return 0;
12461}
12462
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012463sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012464{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012465 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012466 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012467 { # non-public global data
12468 return 0;
12469 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012470
12471 if(defined $SkipInternal)
12472 {
12473 return 0 if($Symbol=~/($SkipInternal)/);
12474 }
12475
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012476 if($CheckObjectsOnly) {
12477 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
12478 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012479 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012480 { # support for old ABI dumps in --headers-only mode
12481 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12482 {
12483 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12484 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012485 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012486 if(not $PType or $PType eq "Unknown") {
12487 return 0;
12488 }
12489 }
12490 }
12491 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012492 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012493 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012494 if($SkipSymbols{$LibVersion}{$Symbol})
12495 { # user defined symbols to ignore
12496 return 0;
12497 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012498 if($SymbolsListPath and not $SymbolsList{$Symbol})
12499 { # user defined symbols
12500 return 0;
12501 }
12502 if($AppPath and not $SymbolsList_App{$Symbol})
12503 { # user defined symbols (in application)
12504 return 0;
12505 }
12506
12507 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12508
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012509 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12510 if(not $NameSpace and $ClassId)
12511 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012512 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012513 }
12514 if($NameSpace)
12515 { # user defined namespaces to ignore
12516 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12517 return 0;
12518 }
12519 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12520 { # nested namespaces
12521 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12522 return 0;
12523 }
12524 }
12525 }
12526 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
12527 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012528 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012529 { # --skip-headers or <skip_headers> (not <skip_including>)
12530 if($Skip==1) {
12531 return 0;
12532 }
12533 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012534 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012535 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012536 { # user defined types
12537 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12538
12539 if(not $TypesList{$CName})
12540 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012541 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12542 {
12543 $CName=~s/\A\Q$NS\E\:\://g;
12544 }
12545
12546 if(not $TypesList{$CName})
12547 {
12548 my $Found = 0;
12549
12550 while($CName=~s/\:\:.+?\Z//)
12551 {
12552 if($TypesList{$CName})
12553 {
12554 $Found = 1;
12555 last;
12556 }
12557 }
12558
12559 if(not $Found) {
12560 return 0;
12561 }
12562 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012563 }
12564 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012565
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012566 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12567 { # non-target symbols
12568 return 0;
12569 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012570 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012571 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012572 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012573 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012574 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012575 return 0;
12576 }
12577 }
12578 else
12579 {
12580 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012581 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012582 {
12583 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12584 { # inline virtual methods
12585 if($Type=~/InlineVirt/) {
12586 return 1;
12587 }
12588 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12589 if(not $Allocable)
12590 { # check bases
12591 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12592 {
12593 if(not isCopyingClass($DCId, $LibVersion))
12594 { # exists a derived class without default c-tor
12595 $Allocable=1;
12596 last;
12597 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012598 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012599 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012600 if(not $Allocable) {
12601 return 0;
12602 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012603 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012604 else
12605 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012606 return 0;
12607 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012608 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012609 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012610 }
12611 }
12612 return 1;
12613}
12614
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012615sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012616{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012617 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012618 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12619 {
12620 if(link_symbol($Symbol, 1, "+Deps"))
12621 { # linker can find a new symbol
12622 # in the old-version library
12623 # So, it's not a new symbol
12624 next;
12625 }
12626 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012627 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012628 next;
12629 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012630 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012631 }
12632}
12633
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012634sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012635{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012636 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012637 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12638 {
12639 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012640 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012641 }
12642 if(link_symbol($Symbol, 2, "+Deps"))
12643 { # linker can find an old symbol
12644 # in the new-version library
12645 next;
12646 }
12647 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012648 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012649 next;
12650 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012651 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012652 }
12653}
12654
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012655sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012656{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012657 my $Level = $_[0];
12658 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012659 { # checking added symbols
12660 next if($CompleteSignature{2}{$Symbol}{"Private"});
12661 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012662 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012663 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012664 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012665 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012666 { # checking removed symbols
12667 next if($CompleteSignature{1}{$Symbol}{"Private"});
12668 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012669 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012670 { # skip v-tables for templates, that should not be imported by applications
12671 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012672 if(my $CName = $VTableClass{$Symbol})
12673 {
12674 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12675 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012676 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012677 next;
12678 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012679 }
12680 }
12681 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012682 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012683 }
12684 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12685 { # symbols for pure virtual methods cannot be called by clients
12686 next;
12687 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012688 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012689 }
12690}
12691
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012692sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012693{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012694 my ($LibVersion, $V) = @_;
12695 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12696 return $Cache{"checkDump"}{$LibVersion}{$V};
12697 }
12698 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012699}
12700
12701sub detectAdded_H($)
12702{
12703 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012704 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12705 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012706 if($Level eq "Source")
12707 { # remove symbol version
12708 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12709 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012710
12711 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12712 { # skip artificial constructors
12713 next;
12714 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012715 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012716 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12717 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012718 next;
12719 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012720 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012721 next;
12722 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012723 if(not defined $CompleteSignature{1}{$Symbol}
12724 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12725 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012726 if($UsedDump{2}{"SrcBin"})
12727 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012728 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012729 { # support for old and different (!) ABI dumps
12730 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12731 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012732 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012733 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012734 {
12735 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12736 {
12737 if($Lang eq "C")
12738 { # support for old ABI dumps: missed extern "C" functions
12739 next;
12740 }
12741 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012742 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012743 else
12744 {
12745 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012746 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012747 next;
12748 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012749 }
12750 }
12751 }
12752 }
12753 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012754 }
12755 }
12756}
12757
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012758sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012759{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012760 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012761 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12762 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012763 if($Level eq "Source")
12764 { # remove symbol version
12765 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12766 $Symbol=$SN;
12767 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012768 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12769 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012770 next;
12771 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012772 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012773 next;
12774 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012775 if(not defined $CompleteSignature{2}{$Symbol}
12776 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012777 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012778 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012779 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012780 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012781 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012782 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12783 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012784 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012785 if($CheckHeadersOnly)
12786 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012787 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12788 {
12789 if($Lang eq "C")
12790 { # support for old ABI dumps: missed extern "C" functions
12791 next;
12792 }
12793 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012794 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012795 else
12796 {
12797 if(not link_symbol($Symbol, 1, "-Deps"))
12798 { # skip removed inline symbols
12799 next;
12800 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012801 }
12802 }
12803 }
12804 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012805 if(not checkDump(1, "2.15"))
12806 {
12807 if($Symbol=~/_IT_E\Z/)
12808 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12809 next;
12810 }
12811 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012812 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12813 {
12814 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12815 {
12816 if(defined $Constants{2}{$Short})
12817 {
12818 my $Val = $Constants{2}{$Short}{"Value"};
12819 if(defined $Func_ShortName{2}{$Val})
12820 { # old name defined to new
12821 next;
12822 }
12823 }
12824 }
12825
12826 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012827 $RemovedInt{$Level}{$Symbol} = 1;
12828 if($Level eq "Source")
12829 { # search for a source-compatible equivalent
12830 setAlternative($Symbol, $Level);
12831 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012832 }
12833 }
12834}
12835
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012836sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012837{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012838 my $Level = $_[0];
12839 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012840 { # checking added symbols
12841 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012842 next if($CompleteSignature{2}{$Symbol}{"Private"});
12843 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012844 if($Level eq "Binary")
12845 {
12846 if($CompleteSignature{2}{$Symbol}{"InLine"})
12847 {
12848 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12849 { # skip inline non-virtual functions
12850 next;
12851 }
12852 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012853 }
12854 else
12855 { # Source
12856 if($SourceAlternative_B{$Symbol}) {
12857 next;
12858 }
12859 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012860 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012861 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012862 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012863 { # checking removed symbols
12864 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012865 next if($CompleteSignature{1}{$Symbol}{"Private"});
12866 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012867 if($Level eq "Binary")
12868 {
12869 if($CompleteSignature{1}{$Symbol}{"InLine"})
12870 {
12871 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12872 { # skip inline non-virtual functions
12873 next;
12874 }
12875 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012876 }
12877 else
12878 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012879 if(my $Alt = $SourceAlternative{$Symbol})
12880 {
12881 if(defined $CompleteSignature{1}{$Alt}
12882 and $CompleteSignature{1}{$Symbol}{"Const"})
12883 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012884 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012885 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012886 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012887 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012888 }
12889 else
12890 { # do NOT show removed symbol
12891 next;
12892 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012893 }
12894 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012895 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012896 }
12897}
12898
12899sub addParamNames($)
12900{
12901 my $LibraryVersion = $_[0];
12902 return if(not keys(%AddIntParams));
12903 my $SecondVersion = $LibraryVersion==1?2:1;
12904 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
12905 {
12906 next if(not keys(%{$AddIntParams{$Interface}}));
12907 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012908 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012909 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
12910 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012911 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012912 if(defined $CompleteSignature{$SecondVersion}{$Interface}
12913 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
12914 {
12915 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
12916 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12917 }
12918 }
12919 else {
12920 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12921 }
12922 }
12923 }
12924 }
12925}
12926
12927sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012928{ # detect changed typedefs to show
12929 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012930 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
12931 {
12932 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012933 my $BName1 = $Typedef_BaseName{1}{$Typedef};
12934 if(not $BName1 or isAnon($BName1)) {
12935 next;
12936 }
12937 my $BName2 = $Typedef_BaseName{2}{$Typedef};
12938 if(not $BName2 or isAnon($BName2)) {
12939 next;
12940 }
12941 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012942 $ChangedTypedef{$Typedef} = 1;
12943 }
12944 }
12945}
12946
12947sub get_symbol_suffix($$)
12948{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012949 my ($Symbol, $Full) = @_;
12950 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040012951 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012952 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012953 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012954 if(not $Full) {
12955 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
12956 }
12957 return $Suffix;
12958}
12959
12960sub get_symbol_prefix($$)
12961{
12962 my ($Symbol, $LibVersion) = @_;
12963 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
12964 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12965 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012966 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012967 }
12968 return $ShortName;
12969}
12970
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012971sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012972{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012973 my $Symbol = $_[0];
12974 my $PSymbol = $Symbol;
12975 if(not defined $CompleteSignature{2}{$PSymbol}
12976 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
12977 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
12978 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012979 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012980 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012981 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012982 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012983 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
12984 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012985 {
12986 if(defined $CompleteSignature{2}{$PSymbol}
12987 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12988 {
12989 $SourceAlternative{$Symbol} = $PSymbol;
12990 $SourceAlternative_B{$PSymbol} = $Symbol;
12991 if(not defined $CompleteSignature{1}{$PSymbol}
12992 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12993 $SourceReplacement{$Symbol} = $PSymbol;
12994 }
12995 }
12996 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012997 }
12998 else
12999 {
13000 foreach my $Sp ("KV", "VK", "K", "V")
13001 {
13002 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13003 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13004 {
13005 if(defined $CompleteSignature{2}{$PSymbol}
13006 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13007 {
13008 $SourceAlternative{$Symbol} = $PSymbol;
13009 $SourceAlternative_B{$PSymbol} = $Symbol;
13010 if(not defined $CompleteSignature{1}{$PSymbol}
13011 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13012 $SourceReplacement{$Symbol} = $PSymbol;
13013 }
13014 }
13015 }
13016 $PSymbol = $Symbol;
13017 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013018 }
13019 }
13020 }
13021 return "";
13022}
13023
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013024sub getSymKind($$)
13025{
13026 my ($Symbol, $LibVersion) = @_;
13027 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13028 {
13029 return "Global_Data";
13030 }
13031 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13032 {
13033 return "Method";
13034 }
13035 return "Function";
13036}
13037
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013038sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013039{
13040 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013041 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013042
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013043 mergeBases($Level);
13044
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013045 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013046 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013047 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013048 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013049 next;
13050 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013051 if(defined $CompleteSignature{1}{$Symbol}
13052 and $CompleteSignature{1}{$Symbol}{"Header"})
13053 { # double-check added symbol
13054 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013055 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013056 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013057 next;
13058 }
13059 if($Symbol=~/\A(_Z|\?)/)
13060 { # C++
13061 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13062 }
13063 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13064 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013065 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13066 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013067 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013068 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013069 {
13070 if($TName_Tid{1}{$AffectedClass_Name})
13071 { # class should exist in previous version
13072 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13073 { # old v-table is NOT copied by old applications
13074 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13075 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013076 "Target"=>get_Signature($Symbol, 2),
13077 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013078 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013079 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013080 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013081 }
13082 }
13083 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013084 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13085 { # check all removed exported symbols
13086 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013087 next;
13088 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013089 if(defined $CompleteSignature{2}{$Symbol}
13090 and $CompleteSignature{2}{$Symbol}{"Header"})
13091 { # double-check removed symbol
13092 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013093 }
13094 if($CompleteSignature{1}{$Symbol}{"Private"})
13095 { # skip private methods
13096 next;
13097 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013098 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013099 next;
13100 }
13101 $CheckedSymbols{$Level}{$Symbol} = 1;
13102 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13103 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013104 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13105 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013106 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013107 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13108 {
13109 if($TName_Tid{2}{$AffectedClass_Name})
13110 { # class should exist in newer version
13111 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13112 { # old v-table is NOT copied by old applications
13113 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13114 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013115 "Target"=>get_Signature($OverriddenMethod, 1),
13116 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013117 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013118 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013119 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013120 }
13121 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013122 if($Level eq "Binary"
13123 and $OSgroup eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013124 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013125 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013126 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013127 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013128 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013129 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013130 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013131 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013132 {
13133 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13134 "Target"=>$tr_name{$Symbol},
13135 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013136 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013137 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013138 else
13139 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013140 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013141 "Target"=>$tr_name{$Symbol},
13142 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013143 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013144 }
13145 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013146 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013147 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013148 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013149 {
13150 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13151 "Target"=>$tr_name{$Symbol},
13152 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013153 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013154 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013155 else
13156 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013157 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013158 "Target"=>$tr_name{$Symbol},
13159 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013160 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013161 }
13162 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013163 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13164 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13165 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13166 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13167 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013168 {
13169 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013170 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013171 $ProblemType = "Global_Data_Symbol_Changed_Type";
13172 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013173 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13174 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013175 "Old_Type"=>$RTName1,
13176 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013177 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013178 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013179 }
13180 }
13181 }
13182 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013183 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013184 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013185 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013186 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013187 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013188 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013189 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013190 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13191 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013192 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013193 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013194 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013195 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013196 }
13197 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013198 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13199 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013200 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013201 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013202 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013203 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013204 }
13205 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013206 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013207 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013208 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013209 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013210 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013211 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013212 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013213 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013214 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013215 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013216 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013217 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013218 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013219 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013220 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013221 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013222 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013223 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013224 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013225 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013226 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013227 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013228 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013229 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013230 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013231 { # "volatile" to non-"volatile"
13232
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013233 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013234 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013235 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013236 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013237 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013238 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013239 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013240 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013241 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013242 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013243 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013244 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013245 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013246 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013247 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013248 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013249 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013250 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13251 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013252 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013253 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013254 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013255 }
13256 }
13257 }
13258 }
13259 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013260 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13261 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013262 $CurrentSymbol = $Symbol;
13263
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013264 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13265 if($Level eq "Source")
13266 { # remove symbol version
13267 $Symbol=$SN;
13268 }
13269 else
13270 { # Binary
13271 if(not $SV)
13272 { # symbol without version
13273 if(my $VSym = $SymVer{1}{$Symbol})
13274 { # the symbol is linked with versioned symbol
13275 if($CompleteSignature{2}{$VSym}{"MnglName"})
13276 { # show report for symbol@ver only
13277 next;
13278 }
13279 elsif(not link_symbol($VSym, 2, "-Deps"))
13280 { # changed version: sym@v1 to sym@v2
13281 # do NOT show report for symbol
13282 next;
13283 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013284 }
13285 }
13286 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013287 my $PSymbol = $Symbol;
13288 if($Level eq "Source"
13289 and my $S = $SourceReplacement{$Symbol})
13290 { # take a source-compatible replacement function
13291 $PSymbol = $S;
13292 }
13293 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013294 { # private symbols
13295 next;
13296 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013297 if(not defined $CompleteSignature{1}{$Symbol}
13298 or not defined $CompleteSignature{2}{$PSymbol})
13299 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013300 next;
13301 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013302 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13303 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13304 { # no mangled name
13305 next;
13306 }
13307 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13308 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013309 { # without a header
13310 next;
13311 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013312
13313 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13314 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13315 { # became pure
13316 next;
13317 }
13318 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13319 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13320 { # became non-pure
13321 next;
13322 }
13323
13324 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13325 { # exported, target, inline virtual and pure virtual
13326 next;
13327 }
13328 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13329 { # exported, target, inline virtual and pure virtual
13330 next;
13331 }
13332
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013333 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013334 {
13335 if($CompleteSignature{1}{$Symbol}{"Data"}
13336 and $CompleteSignature{2}{$PSymbol}{"Data"})
13337 {
13338 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13339 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13340 if(defined $Value1)
13341 {
13342 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13343 if(defined $Value2)
13344 {
13345 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13346 if($Value1 ne $Value2)
13347 {
13348 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13349 "Old_Value"=>$Value1,
13350 "New_Value"=>$Value2,
13351 "Target"=>get_Signature($Symbol, 1) );
13352 }
13353 }
13354 }
13355 }
13356 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013357
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013358 if($CompleteSignature{2}{$PSymbol}{"Private"})
13359 {
13360 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13361 "Target"=>get_Signature_M($PSymbol, 2) );
13362 }
13363 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13364 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13365 {
13366 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13367 "Target"=>get_Signature_M($PSymbol, 2) );
13368 }
13369 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13370 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13371 {
13372 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13373 "Target"=>get_Signature_M($PSymbol, 2) );
13374 }
13375
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013376 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013377 mergeVirtualTables($Symbol, $Level);
13378
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013379 if($COMPILE_ERRORS)
13380 { # if some errors occurred at the compiling stage
13381 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013382 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013383 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013384 { # missed information about parameters in newer version
13385 next;
13386 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013387 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013388 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013389 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013390 next;
13391 }
13392 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013393 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013394 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013395 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013396 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13397 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013398 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13399 "Target"=>get_Signature($Symbol, 1)
13400 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013401 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013402 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013403 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13404 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013405 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013406 "Target"=>get_Signature($Symbol, 1)
13407 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013408 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013409 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13410 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013411 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013412 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013413 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013414 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13415 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13416 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013417 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013418 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013419 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13420 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013421 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013422 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013423 my $ProblemType = "Virtual_Method_Position";
13424 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13425 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013426 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013427 if(isUsedClass($Class_Id, 1, $Level))
13428 {
13429 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013430 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013431 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013432 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13433 next;
13434 }
13435 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013436 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013437 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13438 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013439 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013440 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013441 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013442 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013443 }
13444 }
13445 }
13446 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013447 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13448 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013449 { # do NOT check type changes in pure virtuals
13450 next;
13451 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013452 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013453 if($Symbol=~/\A(_Z|\?)/
13454 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013455 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013456 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013457 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013458 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013459 }
13460 }
13461 else
13462 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013463 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013464 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013465 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013466 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13467 last if($PType2_Name eq "...");
13468 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13469 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013470 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013471 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013472 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013473 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13474 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013475 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13476 $ParamPos_Prev = "lost";
13477 }
13478 }
13479 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013480 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013481 }
13482 if($ParamPos_Prev eq "lost")
13483 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013484 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013485 {
13486 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013487 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013488 $ProblemType = "Added_Unnamed_Parameter";
13489 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013490 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013491 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013492 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013493 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013494 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013495 }
13496 else
13497 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013498 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013499 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013500 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013501 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13502 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013503 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013504 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013505 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013506 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013507 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013508 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013509 "Param_Type"=>$PType2_Name,
13510 "Old_Value"=>$PName_Old,
13511 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013512 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013513 }
13514 }
13515 else
13516 {
13517 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013518 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013519 $ProblemType = "Added_Middle_Unnamed_Parameter";
13520 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013521 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013522 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013523 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013524 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013525 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013526 }
13527 }
13528 }
13529 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013530 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013531 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013532 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013533 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013534 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013535 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013536 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013537 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013538 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013539 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13540 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013541 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013542 }
13543 }
13544 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013545 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013546 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013547 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013548 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13549 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013550 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13551 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013552 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013553 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013554 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013555 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13556 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013557 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13558 $ParamPos_New = "lost";
13559 }
13560 }
13561 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013562 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013563 }
13564 if($ParamPos_New eq "lost")
13565 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013566 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013567 {
13568 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013569 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013570 $ProblemType = "Removed_Unnamed_Parameter";
13571 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013572 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013573 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013574 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013575 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013576 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013577 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013578 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013579 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013580 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013581 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013582 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013583 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013584 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013585 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013586 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013587 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013588 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013589 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013590 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013591 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013592 "Old_Value"=>$PName,
13593 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013594 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013595 }
13596 }
13597 else
13598 {
13599 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013600 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013601 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13602 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013603 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013604 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013605 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013606 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013607 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013608 }
13609 }
13610 }
13611 }
13612 }
13613 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013614 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13615 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013616 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013617
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013618 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013619 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013620 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13621 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013622 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013623
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013624 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013625 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013626 if($SubProblemType eq "Return_Type_And_Size") {
13627 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13628 }
13629 elsif($SubProblemType eq "Return_Type_Format") {
13630 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13631 }
13632 else {
13633 $ProblemTypes{"Global_Data_Type"} = 1;
13634 }
13635
13636 # quals
13637 if($SubProblemType eq "Return_Type"
13638 or $SubProblemType eq "Return_Type_And_Size"
13639 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013640 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013641 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13642 { # const to non-const
13643 if($RR==2) {
13644 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13645 }
13646 else {
13647 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13648 }
13649 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013650 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013651 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13652 { # non-const to const
13653 if($RA==2) {
13654 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13655 }
13656 else {
13657 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13658 }
13659 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013660 }
13661 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013662 }
13663 else
13664 {
13665 # quals
13666 if($SubProblemType eq "Return_Type"
13667 or $SubProblemType eq "Return_Type_And_Size"
13668 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013669 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013670 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013671 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013672 if(addedQual($Old_Value, $New_Value, "volatile"))
13673 {
13674 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13675 if($Level ne "Source"
13676 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13677 $ProblemTypes{"Return_Type"} = 1;
13678 }
13679 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013680 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013681 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13682 {
13683 if($RA==2) {
13684 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13685 }
13686 else {
13687 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13688 }
13689 if($Level ne "Source"
13690 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13691 $ProblemTypes{"Return_Type"} = 1;
13692 }
13693 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013694 }
13695 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013696 if($Level eq "Binary"
13697 and not $CompleteSignature{1}{$Symbol}{"Data"})
13698 {
13699 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13700 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13701 { # if one of the architectures is unknown
13702 # then set other arhitecture to unknown too
13703 ($Arch1, $Arch2) = ("unknown", "unknown");
13704 }
13705 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013706 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013707 {
13708 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13709 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13710 }
13711 else
13712 {
13713 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13714 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13715 }
13716
13717 if($SubProblemType eq "Return_Type_Became_Void")
13718 {
13719 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13720 { # parameters stack has been affected
13721 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013722 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013723 }
13724 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013725 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013726 }
13727 }
13728 }
13729 elsif($SubProblemType eq "Return_Type_From_Void")
13730 {
13731 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13732 { # parameters stack has been affected
13733 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013734 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013735 }
13736 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013737 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013738 }
13739 }
13740 }
13741 elsif($SubProblemType eq "Return_Type"
13742 or $SubProblemType eq "Return_Type_And_Size"
13743 or $SubProblemType eq "Return_Type_Format")
13744 {
13745 if($Conv1{"Method"} ne $Conv2{"Method"})
13746 {
13747 if($Conv1{"Method"} eq "stack")
13748 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013749 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013750 }
13751 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013752 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013753 }
13754 }
13755 else
13756 {
13757 if($Conv1{"Method"} eq "reg")
13758 {
13759 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13760 {
13761 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013762 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013763 }
13764 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013765 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013766 }
13767 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013768 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013769 }
13770 }
13771 }
13772 }
13773 }
13774 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013775
13776 if(not keys(%ProblemTypes))
13777 { # default
13778 $ProblemTypes{$SubProblemType} = 1;
13779 }
13780
13781 foreach my $ProblemType (keys(%ProblemTypes))
13782 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013783 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013784 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013785 }
13786 if($ReturnType1_Id and $ReturnType2_Id)
13787 {
13788 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013789 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13790
13791 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013792
13793 if($CompleteSignature{1}{$Symbol}{"Data"})
13794 {
13795 if($Level eq "Binary")
13796 {
13797 if(get_PLevel($ReturnType1_Id, 1)==0)
13798 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013799 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013800 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013801
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013802 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13803 {
13804 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013805 {
13806 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13807 {
13808 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13809 last;
13810 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013811 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013812 }
13813 }
13814 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013815 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013816 {
13817 if(defined $GlobalDataObject{1}{$Symbol}
13818 and defined $GlobalDataObject{2}{$Symbol})
13819 {
13820 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13821 my $New_Size = $GlobalDataObject{2}{$Symbol};
13822 if($Old_Size!=$New_Size)
13823 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013824 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013825 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013826 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013827 }
13828 }
13829 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013830 }
13831 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013832
13833 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013834 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013835 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013836 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013837 my $NewLocation = "retval";
13838 if($SubLocation and $SubLocation ne "retval") {
13839 $NewLocation = "retval->".$SubLocation;
13840 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013841 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13842 }
13843 }
13844
13845 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13846 {
13847 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13848 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013849 my $NewLocation = "retval";
13850 if($SubLocation and $SubLocation ne "retval") {
13851 $NewLocation = "retval->".$SubLocation;
13852 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013853 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013854 }
13855 }
13856 }
13857
13858 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013859 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13860 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13861 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013862 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013863 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013864 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13865 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013866 if($ThisPtr1_Id and $ThisPtr2_Id)
13867 {
13868 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013869 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13870 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013871 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013872 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013873 {
13874 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013875 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013876 }
13877 }
13878 }
13879 }
13880 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013881 if($Level eq "Binary") {
13882 mergeVTables($Level);
13883 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013884 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13885 $CheckedSymbols{$Level}{$Symbol} = 1;
13886 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013887}
13888
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013889sub rmQuals($$)
13890{
13891 my ($Value, $Qual) = @_;
13892 if(not $Qual) {
13893 return $Value;
13894 }
13895 if($Qual eq "all")
13896 { # all quals
13897 $Qual = "const|volatile|restrict";
13898 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013899 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013900 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013901 }
13902 return $Value;
13903}
13904
13905sub cmpBTypes($$$$)
13906{
13907 my ($T1, $T2, $V1, $V2) = @_;
13908 $T1 = uncover_typedefs($T1, $V1);
13909 $T2 = uncover_typedefs($T2, $V2);
13910 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
13911}
13912
13913sub addedQual($$$)
13914{
13915 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013916 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013917}
13918
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013919sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013920{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013921 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013922 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013923}
13924
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013925sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013926{
13927 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
13928 $Old_Value = uncover_typedefs($Old_Value, $V1);
13929 $New_Value = uncover_typedefs($New_Value, $V2);
13930 if($Old_Value eq $New_Value)
13931 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013932 return 0;
13933 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013934 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013935 { # without a qual
13936 return 0;
13937 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013938 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013939 { # became non-qual
13940 return 1;
13941 }
13942 else
13943 {
13944 my @BQ1 = getQualModel($Old_Value, $Qual);
13945 my @BQ2 = getQualModel($New_Value, $Qual);
13946 foreach (0 .. $#BQ1)
13947 { # removed qual
13948 if($BQ1[$_]==1
13949 and $BQ2[$_]!=1)
13950 {
13951 return 2;
13952 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013953 }
13954 }
13955 return 0;
13956}
13957
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013958sub getQualModel($$)
13959{
13960 my ($Value, $Qual) = @_;
13961 if(not $Qual) {
13962 return $Value;
13963 }
13964
13965 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013966 while($Value=~/(\w+)/ and $1 ne $Qual) {
13967 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013968 }
13969 $Value=~s/[^\*\&\w]+//g;
13970
13971 # modeling
13972 # int*const*const == 011
13973 # int**const == 001
13974 my @Model = ();
13975 my @Elems = split(/[\*\&]/, $Value);
13976 if(not @Elems) {
13977 return (0);
13978 }
13979 foreach (@Elems)
13980 {
13981 if($_ eq $Qual) {
13982 push(@Model, 1);
13983 }
13984 else {
13985 push(@Model, 0);
13986 }
13987 }
13988
13989 return @Model;
13990}
13991
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013992my %StringTypes = map {$_=>1} (
13993 "char*",
13994 "char const*"
13995);
13996
13997my %CharTypes = map {$_=>1} (
13998 "char",
13999 "char const"
14000);
14001
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014002sub showVal($$$)
14003{
14004 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014005 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014006 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014007 if(substr($Value, 0, 2) eq "_Z")
14008 {
14009 if(my $Unmangled = $tr_name{$Value}) {
14010 return $Unmangled;
14011 }
14012 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014013 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014014 { # strings
14015 return "\"$Value\"";
14016 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014017 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014018 { # characters
14019 return "\'$Value\'";
14020 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014021 if($Value eq "")
14022 { # other
14023 return "\'\'";
14024 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014025 return $Value;
14026}
14027
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014028sub getRegs($$$)
14029{
14030 my ($LibVersion, $Symbol, $Pos) = @_;
14031
14032 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14033 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014034 my %Regs = ();
14035 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14036 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014037 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014038 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14039 }
14040 }
14041
14042 return join(", ", sort keys(%Regs));
14043 }
14044
14045 return undef;
14046}
14047
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014048sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014049{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014050 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014051 if(not $Symbol) {
14052 return;
14053 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014054 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14055 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14056 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14057 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014058 if(not $PType1_Id
14059 or not $PType2_Id) {
14060 return;
14061 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014062
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014063 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014064 { # do not merge "this"
14065 if($PName1 eq "this" or $PName2 eq "this") {
14066 return;
14067 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014068 }
14069
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014070 my %Type1 = get_Type($PType1_Id, 1);
14071 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014072
14073 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14074
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014075 my %BaseType1 = get_BaseType($PType1_Id, 1);
14076 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014077
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014078 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014079
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014080 if($Level eq "Binary")
14081 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014082 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014083 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14084 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14085 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14086 {
14087 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014088 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014089 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014090 }
14091 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14092 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14093 {
14094 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014095 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014096 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014097 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014098 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014099
14100 if(defined $UsedDump{1}{"DWARF"}
14101 and defined $UsedDump{2}{"DWARF"})
14102 {
14103 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14104 {
14105 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14106 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14107 if($Old_Regs and $New_Regs)
14108 {
14109 if($Old_Regs ne $New_Regs)
14110 {
14111 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14112 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014113 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014114 "Old_Value"=>$Old_Regs,
14115 "New_Value"=>$New_Regs );
14116 }
14117 }
14118 elsif($Old_Regs and not $New_Regs)
14119 {
14120 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14121 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014122 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014123 "Old_Value"=>$Old_Regs );
14124 }
14125 elsif(not $Old_Regs and $New_Regs)
14126 {
14127 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14128 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014129 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014130 "New_Value"=>$New_Regs );
14131 }
14132 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14133 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14134 {
14135 if($Old_Offset ne $New_Offset)
14136 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014137 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14138 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14139
14140 $Old_Offset = $Old_Offset - $Start1;
14141 $New_Offset = $New_Offset - $Start2;
14142
14143 if($Old_Offset ne $New_Offset)
14144 {
14145 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14146 "Target"=>$PName1,
14147 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14148 "Old_Value"=>$Old_Offset,
14149 "New_Value"=>$New_Offset );
14150 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014151 }
14152 }
14153 }
14154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014155 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014156 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14157 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014158 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014159 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014160 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14161 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014162 if(not checkDump(1, "2.13")
14163 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014164 { # support for old ABI dumps
14165 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014166 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014167 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014168 and $Value_Old eq "false" and $Value_New eq "0")
14169 { # int class::method ( bool p = 0 );
14170 # old ABI dumps: "false"
14171 # new ABI dumps: "0"
14172 $Value_Old = "0";
14173 }
14174 }
14175 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014176 if(not checkDump(1, "2.18")
14177 and checkDump(2, "2.18"))
14178 { # support for old ABI dumps
14179 if(not defined $Value_Old
14180 and substr($Value_New, 0, 2) eq "_Z") {
14181 $Value_Old = $Value_New;
14182 }
14183 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014184 if(defined $Value_Old)
14185 {
14186 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14187 if(defined $Value_New)
14188 {
14189 $Value_New = showVal($Value_New, $PType2_Id, 2);
14190 if($Value_Old ne $Value_New)
14191 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014192 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014193 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014194 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014195 "Old_Value"=>$Value_Old,
14196 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014197 }
14198 }
14199 else
14200 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014201 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014202 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014203 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014204 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014205 }
14206 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014207 elsif(defined $Value_New)
14208 {
14209 $Value_New = showVal($Value_New, $PType2_Id, 2);
14210 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14211 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014212 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014213 "New_Value"=>$Value_New );
14214 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014215 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014216
14217 if($ChkRnmd)
14218 {
14219 if($PName1 and $PName2 and $PName1 ne $PName2
14220 and $PType1_Id!=-1 and $PType2_Id!=-1
14221 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14222 { # except unnamed "..." value list (Id=-1)
14223 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14224 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014225 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014226 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14227 "Old_Value"=>$PName1,
14228 "New_Value"=>$PName2,
14229 "New_Signature"=>get_Signature($Symbol, 2) );
14230 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014231 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014232
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014233 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014234 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014235
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014236 foreach my $SubProblemType (keys(%SubProblems))
14237 { # add new problems, remove false alarms
14238 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14239 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014240
14241 # quals
14242 if($SubProblemType eq "Parameter_Type"
14243 or $SubProblemType eq "Parameter_Type_And_Size"
14244 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014245 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014246 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014247 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014248 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014249 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014250 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014251 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14252 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14253 }
14254 }
14255 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14256 {
14257 if(removedQual($Old_Value, $New_Value, "volatile")) {
14258 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014259 }
14260 }
14261 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14262 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14263 { # int to "int const"
14264 delete($SubProblems{$SubProblemType});
14265 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014266 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014267 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14268 { # "int const" to int
14269 delete($SubProblems{$SubProblemType});
14270 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014271 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14272 { # "const" to non-"const"
14273 if($RR==2) {
14274 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14275 }
14276 else {
14277 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14278 }
14279 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014280 }
14281 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014282
14283 if($Level eq "Source")
14284 {
14285 foreach my $SubProblemType (keys(%SubProblems))
14286 {
14287 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14288 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14289
14290 if($SubProblemType eq "Parameter_Type")
14291 {
14292 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14293 delete($SubProblems{$SubProblemType});
14294 }
14295 }
14296 }
14297 }
14298
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014299 foreach my $SubProblemType (keys(%SubProblems))
14300 { # modify/register problems
14301 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14302 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014303 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14304 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014305
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014306 my $NewProblemType = $SubProblemType;
14307 if($Old_Value eq "..." and $New_Value ne "...")
14308 { # change from "..." to "int"
14309 if($ParamPos1==0)
14310 { # ISO C requires a named argument before "..."
14311 next;
14312 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014313 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014314 }
14315 elsif($New_Value eq "..." and $Old_Value ne "...")
14316 { # change from "int" to "..."
14317 if($ParamPos2==0)
14318 { # ISO C requires a named argument before "..."
14319 next;
14320 }
14321 $NewProblemType = "Parameter_Became_VaList";
14322 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014323 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014324 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014325 {
14326 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014327 if($Arch1 eq "unknown"
14328 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014329 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014330 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014331 ($Arch1, $Arch2) = ("unknown", "unknown");
14332 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014333 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014334 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014335 { # real
14336 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14337 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14338 }
14339 else
14340 { # model
14341 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14342 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14343 }
14344 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014345 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014346 if($Conv1{"Method"} eq "stack")
14347 {
14348 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14349 $NewProblemType = "Parameter_Type_And_Stack";
14350 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014351 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014352 elsif($Conv1{"Method"} eq "reg")
14353 {
14354 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14355 $NewProblemType = "Parameter_Type_And_Register";
14356 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014357 }
14358 }
14359 else
14360 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014361 if($Conv1{"Method"} eq "stack") {
14362 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014363 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014364 elsif($Conv1{"Method"} eq "register") {
14365 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014366 }
14367 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014368 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14369 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014370 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014371 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014372 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014373 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014374 "New_Signature"=>get_Signature($Symbol, 2) );
14375 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014376 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014377
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014378 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014379
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014380 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014381 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14382 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014383 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014384 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014385 {
14386 my $NewProblemType = $SubProblemType;
14387 if($SubProblemType eq "DataType_Size")
14388 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014389 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014390 { # stack has been affected
14391 $NewProblemType = "DataType_Size_And_Stack";
14392 }
14393 }
14394 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014395 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014396 }
14397 }
14398}
14399
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014400sub find_ParamPair_Pos_byName($$$)
14401{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014402 my ($Name, $Symbol, $LibVersion) = @_;
14403 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014404 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014405 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14406 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014407 {
14408 return $ParamPos;
14409 }
14410 }
14411 return "lost";
14412}
14413
14414sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14415{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014416 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014417 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014418 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014419 {
14420 next if($Order eq "backward" and $ParamPos>$MediumPos);
14421 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014422 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14423 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014424 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014425 push(@Positions, $ParamPos);
14426 }
14427 }
14428 return @Positions;
14429}
14430
14431sub getTypeIdByName($$)
14432{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014433 my ($TypeName, $LibVersion) = @_;
14434 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014435}
14436
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014437sub diffTypes($$$)
14438{
14439 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14440 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14441 }
14442 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14443 { # skip recursive declarations
14444 return 0;
14445 }
14446
14447 pushType($_[0], $_[1], \@RecurTypes_Diff);
14448 my $Diff = diffTypes_I(@_);
14449 pop(@RecurTypes_Diff);
14450
14451 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14452}
14453
14454sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014455{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014456 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014457
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014458 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14459 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014460
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014461 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14462 { # equal types
14463 return 0;
14464 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014465 if($Type1_Pure{"Name"} eq "void")
14466 { # from void* to something
14467 return 0;
14468 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014469 if($Type1_Pure{"Name"}=~/\*/
14470 or $Type2_Pure{"Name"}=~/\*/)
14471 { # compared in detectTypeChange()
14472 return 0;
14473 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014474
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014475 my %FloatType = map {$_=>1} (
14476 "float",
14477 "double",
14478 "long double"
14479 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014480
14481 my $T1 = $Type1_Pure{"Type"};
14482 my $T2 = $Type2_Pure{"Type"};
14483
14484 if($T1 eq "Struct"
14485 and $T2 eq "Class")
14486 { # compare as data structures
14487 $T2 = "Struct";
14488 }
14489
14490 if($T1 eq "Class"
14491 and $T2 eq "Struct")
14492 { # compare as data structures
14493 $T1 = "Struct";
14494 }
14495
14496 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014497 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014498 if($T1 eq "Intrinsic"
14499 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014500 { # "int" to "enum"
14501 return 0;
14502 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014503 elsif($T2 eq "Intrinsic"
14504 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014505 { # "enum" to "int"
14506 return 0;
14507 }
14508 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014509 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014510 # ...
14511 return 1;
14512 }
14513 }
14514 else
14515 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014516 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014517 {
14518 if($FloatType{$Type1_Pure{"Name"}}
14519 or $FloatType{$Type2_Pure{"Name"}})
14520 { # "float" to "double"
14521 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014522 if($Level eq "Source")
14523 { # Safe
14524 return 0;
14525 }
14526 else {
14527 return 1;
14528 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014529 }
14530 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014531 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014532 {
14533 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14534 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014535 if(not @Membs1
14536 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014537 { # private
14538 return 0;
14539 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014540 if($#Membs1!=$#Membs2)
14541 { # different number of elements
14542 return 1;
14543 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014544 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014545 {
14546 foreach my $Pos (@Membs1)
14547 { # compare elements by name and value
14548 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14549 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14550 { # different names
14551 return 1;
14552 }
14553 }
14554 }
14555 else
14556 {
14557 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014558 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014559 if($Level eq "Source")
14560 {
14561 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14562 { # different names
14563 return 1;
14564 }
14565 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014566
14567 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14568 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14569
14570 if($MT1{"Name"} ne $MT2{"Name"}
14571 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14572 {
14573 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14574 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14575
14576 if($PL1 ne $PL2)
14577 { # different pointer level
14578 return 1;
14579 }
14580
14581 # compare base types
14582 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14583 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14584
14585 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14586 { # different types
14587 return 1;
14588 }
14589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014590 }
14591 }
14592 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014593 else
14594 {
14595 # TODO: arrays, etc.
14596 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014597 }
14598 return 0;
14599}
14600
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014601sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014602{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014603 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014604 if(not $Type1_Id or not $Type2_Id) {
14605 return ();
14606 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014607 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014608 my %Type1 = get_Type($Type1_Id, 1);
14609 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014610 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14611 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14612 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14613 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 +040014614
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014615 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14616 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014617 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14618 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14619 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14620 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14621 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14622 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14623 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014624 if($Type1{"Name"} eq $Type2{"Name"})
14625 {
14626 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14627 { # will be reported in mergeTypes() as typedef problem
14628 return ();
14629 }
14630 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14631 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14632 if(%Typedef_1 and %Typedef_2)
14633 {
14634 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14635 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14636 { # const Typedef
14637 return ();
14638 }
14639 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014640 }
14641 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14642 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014643 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014644 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14645 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014646 {
14647 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14648 "Old_Value"=>$Type1_Base{"Name"},
14649 "New_Value"=>$Type2_Base{"Name"},
14650 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014651 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014652 }
14653 else
14654 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014655 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014656 { # format change
14657 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14658 "Old_Value"=>$Type1_Base{"Name"},
14659 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014660 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014661 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014662 }
14663 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14664 {
14665 %{$LocalProblems{$Prefix."_BaseType"}}=(
14666 "Old_Value"=>$Type1_Base{"Name"},
14667 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014668 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014669 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014670 }
14671 }
14672 }
14673 }
14674 elsif($Type1{"Name"} ne $Type2{"Name"})
14675 { # type change
14676 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14677 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014678 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014679 and $Type1_Pure{"Name"} eq "void")
14680 {
14681 %{$LocalProblems{"Return_Type_From_Void"}}=(
14682 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014683 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014684 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014685 elsif($Prefix eq "Return"
14686 and $Type2_Pure{"Name"} eq "void")
14687 {
14688 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14689 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014690 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014691 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014692 else
14693 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014694 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014695 and $Type1{"Size"} and $Type2{"Size"}
14696 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014697 {
14698 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14699 "Old_Value"=>$Type1{"Name"},
14700 "New_Value"=>$Type2{"Name"},
14701 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014702 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014703 }
14704 else
14705 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014706 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014707 { # format change
14708 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14709 "Old_Value"=>$Type1{"Name"},
14710 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014711 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014712 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014713 }
14714 elsif(tNameLock($Type1_Id, $Type2_Id))
14715 { # FIXME: correct this condition
14716 %{$LocalProblems{$Prefix."_Type"}}=(
14717 "Old_Value"=>$Type1{"Name"},
14718 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014719 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014720 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014721 }
14722 }
14723 }
14724 }
14725 }
14726 if($Type1_PLevel!=$Type2_PLevel)
14727 {
14728 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14729 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14730 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014731 if($Level eq "Source")
14732 {
14733 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014734 "Old_Value"=>$Type1_PLevel,
14735 "New_Value"=>$Type2_PLevel);
14736 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014737 else
14738 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014739 if($Type2_PLevel>$Type1_PLevel)
14740 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014741 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14742 "Old_Value"=>$Type1_PLevel,
14743 "New_Value"=>$Type2_PLevel);
14744 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014745 else
14746 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014747 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14748 "Old_Value"=>$Type1_PLevel,
14749 "New_Value"=>$Type2_PLevel);
14750 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014751 }
14752 }
14753 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014754 if($Type1_Pure{"Type"} eq "Array"
14755 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014756 { # base_type[N] -> base_type[N]
14757 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014758 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014759 foreach my $SubProblemType (keys(%SubProblems))
14760 {
14761 $SubProblemType=~s/_Type/_BaseType/g;
14762 next if(defined $LocalProblems{$SubProblemType});
14763 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14764 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14765 }
14766 }
14767 }
14768 return %LocalProblems;
14769}
14770
14771sub tNameLock($$)
14772{
14773 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014774 my $Changed = 0;
14775 if(differentDumps("G"))
14776 { # different GCC versions
14777 $Changed = 1;
14778 }
14779 elsif(differentDumps("V"))
14780 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014781 if(not checkDump(1, "2.20")
14782 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014783 { # latest names update
14784 # 2.6: added restrict qualifier
14785 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014786 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014787 $Changed = 1;
14788 }
14789 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014790
14791 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14792 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14793
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014794 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14795 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14796
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014797 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014798 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014799 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014800 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014801 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014802 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014803 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014804 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014805 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014806 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014807 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14808 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14809 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014810 { # equal base types
14811 return 0;
14812 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014813
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014814 if(not checkDump(1, "2.13")
14815 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014816 { # broken array names in ABI dumps < 2.13
14817 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014818 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014819 return 0;
14820 }
14821 }
14822
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014823 if(not checkDump(1, "2.6")
14824 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014825 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014826 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014827 and $TN2=~/\brestrict\b/) {
14828 return 0;
14829 }
14830 }
14831
14832 if(not checkDump(1, "2.20")
14833 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014834 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014835 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14836 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014837 return 0;
14838 }
14839 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014840 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014841 else
14842 {
14843 # typedef struct {...} type_t
14844 # typedef struct type_t {...} type_t
14845 if(index($TN1, " ".$TN2)!=-1)
14846 {
14847 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14848 return 0;
14849 }
14850 }
14851 if(index($TN2, " ".$TN1)!=-1)
14852 {
14853 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14854 return 0;
14855 }
14856 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014857
14858 if($TT1 eq "FuncPtr"
14859 and $TT2 eq "FuncPtr")
14860 {
14861 my $TN1_C = $TN1;
14862 my $TN2_C = $TN2;
14863
14864 $TN1_C=~s/\b(struct|union) //g;
14865 $TN2_C=~s/\b(struct|union) //g;
14866
14867 if($TN1_C eq $TN2_C) {
14868 return 0;
14869 }
14870 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014871 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014872
14873 my ($N1, $N2) = ($TN1, $TN2);
14874 $N1=~s/\b(struct|union) //g;
14875 $N2=~s/\b(struct|union) //g;
14876
14877 if($N1 eq $N2)
14878 { # QList<struct QUrl> and QList<QUrl>
14879 return 0;
14880 }
14881
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014882 return 1;
14883}
14884
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014885sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014886{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014887 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014888 if(defined $Cache{"differentDumps"}{$Check}) {
14889 return $Cache{"differentDumps"}{$Check};
14890 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014891 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014892 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014893 if($Check eq "G")
14894 {
14895 if(getGccVersion(1) ne getGccVersion(2))
14896 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014897 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014898 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014899 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014900 if($Check eq "V")
14901 {
14902 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14903 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14904 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014905 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014906 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014907 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014908 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014909 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014910}
14911
14912sub formatVersion($$)
14913{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014914 my ($V, $Digits) = @_;
14915 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014916 return join(".", splice(@Elems, 0, $Digits));
14917}
14918
14919sub htmlSpecChars($)
14920{
14921 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014922 if(not $Str) {
14923 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014924 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014925 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14926 $Str=~s/</&lt;/g;
14927 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
14928 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014929 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
14930 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014931 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014932 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014933 $Str=~s/\n/<br\/>/g;
14934 $Str=~s/\"/&quot;/g;
14935 $Str=~s/\'/&#39;/g;
14936 return $Str;
14937}
14938
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014939sub xmlSpecChars($)
14940{
14941 my $Str = $_[0];
14942 if(not $Str) {
14943 return $Str;
14944 }
14945
14946 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14947 $Str=~s/</&lt;/g;
14948 $Str=~s/>/&gt;/g;
14949
14950 $Str=~s/\"/&quot;/g;
14951 $Str=~s/\'/&#39;/g;
14952
14953 return $Str;
14954}
14955
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014956sub xmlSpecChars_R($)
14957{
14958 my $Str = $_[0];
14959 if(not $Str) {
14960 return $Str;
14961 }
14962
14963 $Str=~s/&amp;/&/g;
14964 $Str=~s/&lt;/</g;
14965 $Str=~s/&gt;/>/g;
14966
14967 $Str=~s/&quot;/"/g;
14968 $Str=~s/&#39;/'/g;
14969
14970 return $Str;
14971}
14972
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014973sub black_name($)
14974{
14975 my $Name = $_[0];
14976 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
14977}
14978
14979sub highLight_Signature($)
14980{
14981 my $Signature = $_[0];
14982 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
14983}
14984
14985sub highLight_Signature_Italic_Color($)
14986{
14987 my $Signature = $_[0];
14988 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
14989}
14990
14991sub separate_symbol($)
14992{
14993 my $Symbol = $_[0];
14994 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
14995 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
14996 ($Name, $Spec, $Ver) = ($1, $2, $3);
14997 }
14998 return ($Name, $Spec, $Ver);
14999}
15000
15001sub cut_f_attrs($)
15002{
15003 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15004 return $2;
15005 }
15006 return "";
15007}
15008
15009sub highLight_Signature_PPos_Italic($$$$$)
15010{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015011 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15012 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015013 if($CheckObjectsOnly) {
15014 $ItalicParams=$ColorParams=0;
15015 }
15016 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15017 my $Return = "";
15018 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15019 $Return = $2;
15020 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015021 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015022 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015023 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015024 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015025 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015026 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015027 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015028 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015029 }
15030 return $Signature;
15031 }
15032 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15033 $Begin.=" " if($Begin!~/ \Z/);
15034 $End = cut_f_attrs($Signature);
15035 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015036 my ($Short, $Params) = split_Signature($Signature);
15037 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015038 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015039 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015040 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015041 $Part=~s/\A\s+|\s+\Z//g;
15042 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15043 if($Part=~/\([\*]+(\w+)\)/i) {
15044 $ParamName = $1;#func-ptr
15045 }
15046 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15047 $ParamName = $1;
15048 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015049 if(not $ParamName)
15050 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015051 push(@Parts, $Part_Styled);
15052 next;
15053 }
15054 if($ItalicParams and not $TName_Tid{1}{$Part}
15055 and not $TName_Tid{2}{$Part})
15056 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015057 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015058 if($Param_Pos ne ""
15059 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015060 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015061 }
15062 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015063 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015064 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015065 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015066 }
15067 $Part_Styled=~s/,(\w)/, $1/g;
15068 push(@Parts, $Part_Styled);
15069 }
15070 if(@Parts)
15071 {
15072 foreach my $Num (0 .. $#Parts)
15073 {
15074 if($Num==$#Parts)
15075 { # add ")" to the last parameter
15076 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15077 }
15078 elsif(length($Parts[$Num])<=45) {
15079 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15080 }
15081 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015082 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015083 }
15084 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015085 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015086 }
15087 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015088 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015089 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015090 $Signature=~s!\[\]![&#160;]!g;
15091 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015092 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15093 if($SymbolVersion) {
15094 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15095 }
15096 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015097}
15098
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015099sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015100{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015101 my $Signature = $_[0];
15102 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15103 {
15104 $Signature=~s/\A\Q$ShortName\E\(//g;
15105 cut_f_attrs($Signature);
15106 $Signature=~s/\)\Z//;
15107 return ($ShortName, $Signature);
15108 }
15109
15110 # error
15111 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015112}
15113
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015114sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015115{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015116 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015117 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015118 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15119 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015120 foreach my $Pos (0 .. length($Params) - 1)
15121 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015122 my $S = substr($Params, $Pos, 1);
15123 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015124 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015125 }
15126 if($S eq "," and
15127 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015128 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015129 if($Comma)
15130 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015131 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015132 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015133 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015134 }
15135 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015136 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015137 }
15138 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015139 if(not $Sp)
15140 { # remove spaces
15141 foreach (@Parts)
15142 {
15143 s/\A //g;
15144 s/ \Z//g;
15145 }
15146 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015147 return @Parts;
15148}
15149
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015150sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015151{
15152 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015153 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015154 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015155 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15156 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015157 $Center+=length($1);
15158 }
15159 foreach my $Pos (0 .. length($Sign)-1)
15160 {
15161 my $S = substr($Sign, $Pos, 1);
15162 if($S eq $Target)
15163 {
15164 if($B{"("}==$B{")"}
15165 and $B{"<"}==$B{">"}) {
15166 return $Center;
15167 }
15168 }
15169 if(defined $B{$S}) {
15170 $B{$S}+=1;
15171 }
15172 $Center+=1;
15173 }
15174 return 0;
15175}
15176
15177sub appendFile($$)
15178{
15179 my ($Path, $Content) = @_;
15180 return if(not $Path);
15181 if(my $Dir = get_dirname($Path)) {
15182 mkpath($Dir);
15183 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015184 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015185 print FILE $Content;
15186 close(FILE);
15187}
15188
15189sub writeFile($$)
15190{
15191 my ($Path, $Content) = @_;
15192 return if(not $Path);
15193 if(my $Dir = get_dirname($Path)) {
15194 mkpath($Dir);
15195 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015196 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015197 print FILE $Content;
15198 close(FILE);
15199}
15200
15201sub readFile($)
15202{
15203 my $Path = $_[0];
15204 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015205 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015206 local $/ = undef;
15207 my $Content = <FILE>;
15208 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015209 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015210 $Content=~s/\r/\n/g;
15211 }
15212 return $Content;
15213}
15214
15215sub get_filename($)
15216{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015217 if(defined $Cache{"get_filename"}{$_[0]}) {
15218 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015219 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015220 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15221 return ($Cache{"get_filename"}{$_[0]}=$1);
15222 }
15223 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015224}
15225
15226sub get_dirname($)
15227{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015228 if(defined $Cache{"get_dirname"}{$_[0]}) {
15229 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015230 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015231 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15232 return ($Cache{"get_dirname"}{$_[0]}=$1);
15233 }
15234 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015235}
15236
15237sub separate_path($) {
15238 return (get_dirname($_[0]), get_filename($_[0]));
15239}
15240
15241sub esc($)
15242{
15243 my $Str = $_[0];
15244 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15245 return $Str;
15246}
15247
15248sub readLineNum($$)
15249{
15250 my ($Path, $Num) = @_;
15251 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015252 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015253 foreach (1 ... $Num) {
15254 <FILE>;
15255 }
15256 my $Line = <FILE>;
15257 close(FILE);
15258 return $Line;
15259}
15260
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015261sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015262{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015263 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015264 return () if(not $Path or not -f $Path);
15265 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015266 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15267 {
15268 foreach my $AttrVal (split(/;/, $1))
15269 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015270 if($AttrVal=~/(.+):(.+)/)
15271 {
15272 my ($Name, $Value) = ($1, $2);
15273 $Attributes{$Name} = $Value;
15274 }
15275 }
15276 }
15277 return \%Attributes;
15278}
15279
15280sub is_abs($) {
15281 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15282}
15283
15284sub get_abs_path($)
15285{ # abs_path() should NOT be called for absolute inputs
15286 # because it can change them
15287 my $Path = $_[0];
15288 if(not is_abs($Path)) {
15289 $Path = abs_path($Path);
15290 }
15291 return $Path;
15292}
15293
15294sub get_OSgroup()
15295{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015296 my $N = $Config{"osname"};
15297 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015298 return "macos";
15299 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015300 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015301 return "bsd";
15302 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015303 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015304 return "beos";
15305 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015306 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015307 return "symbian";
15308 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015309 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015310 return "windows";
15311 }
15312 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015313 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015314 }
15315}
15316
15317sub getGccVersion($)
15318{
15319 my $LibVersion = $_[0];
15320 if($GCC_VERSION{$LibVersion})
15321 { # dump version
15322 return $GCC_VERSION{$LibVersion};
15323 }
15324 elsif($UsedDump{$LibVersion}{"V"})
15325 { # old-version dumps
15326 return "unknown";
15327 }
15328 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15329 if(not $GccVersion) {
15330 return "unknown";
15331 }
15332 return $GccVersion;
15333}
15334
15335sub showArch($)
15336{
15337 my $Arch = $_[0];
15338 if($Arch eq "arm"
15339 or $Arch eq "mips") {
15340 return uc($Arch);
15341 }
15342 return $Arch;
15343}
15344
15345sub getArch($)
15346{
15347 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015348
15349 if($TargetArch) {
15350 return $TargetArch;
15351 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015352 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015353 { # dump version
15354 return $CPU_ARCH{$LibVersion};
15355 }
15356 elsif($UsedDump{$LibVersion}{"V"})
15357 { # old-version dumps
15358 return "unknown";
15359 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015360
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015361 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015362}
15363
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015364sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015365{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015366 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015367
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015368 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015369 if(getArch(1) ne getArch(2)
15370 or getArch(1) eq "unknown"
15371 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015372 { # don't show architecture in the header
15373 $ArchInfo="";
15374 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015375 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015376 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015377 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015378 }
15379 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015380 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015381 }
15382 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015383 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015384 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015385
15386 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15387 {
15388 my $M1 = $UsedDump{1}{"M"};
15389 my $M2 = $UsedDump{2}{"M"};
15390
15391 if($M1 eq $M2)
15392 {
15393 $Title .= " report for the <span style='color:Blue;'>$M1</span> object";
15394 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15395 }
15396 else
15397 {
15398 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$Descriptor{1}{"Version"}."</span>)";
15399 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$Descriptor{2}{"Version"}."</span>) objects";
15400 }
15401 }
15402 else
15403 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015404 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015405 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15406 }
15407
15408 $Title .= $ArchInfo;
15409
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015410 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015411 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015412 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015413 $Title = "<h1>".$Title."</h1>\n";
15414 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015415}
15416
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015417sub get_CheckedHeaders($)
15418{
15419 my $LibVersion = $_[0];
15420
15421 my @Headers = ();
15422
15423 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15424 {
15425 my $File = get_filename($Path);
15426 if(not is_target_header($File, $LibVersion)) {
15427 next;
15428 }
15429
15430 if(skipHeader($File, $LibVersion)) {
15431 next;
15432 }
15433
15434 push(@Headers, $Path);
15435 }
15436
15437 return @Headers;
15438}
15439
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015440sub get_SourceInfo()
15441{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015442 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015443 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015444 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015445 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015446 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015447 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15448 $CheckedHeaders .= "<div class='h_list'>\n";
15449 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15450 {
15451 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15452 my $Name = get_filename($Identity);
15453 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15454 $CheckedHeaders .= $Name.$Comment."<br/>\n";
15455 }
15456 $CheckedHeaders .= "</div>\n";
15457 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015458 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015459
15460 if(my @Sources = keys(%{$Registered_Sources{1}}))
15461 {
15462 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15463 $CheckedSources .= "<div class='h_list'>\n";
15464 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15465 {
15466 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15467 my $Name = get_filename($Identity);
15468 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15469 $CheckedSources .= $Name.$Comment."<br/>\n";
15470 }
15471 $CheckedSources .= "</div>\n";
15472 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15473 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015474 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015475 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015476 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015477 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015478 $CheckedLibs .= "<div class='lib_list'>\n";
15479 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15480 {
15481 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15482 $CheckedLibs .= $Library."<br/>\n";
15483 }
15484 $CheckedLibs .= "</div>\n";
15485 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015486 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015487 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15488}
15489
15490sub get_ObjTitle()
15491{
15492 if(defined $UsedDump{1}{"DWARF"}) {
15493 return "Objects";
15494 }
15495 else {
15496 return ucfirst($SLIB_TYPE)." Libraries";
15497 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015498}
15499
15500sub get_TypeProblems_Count($$$)
15501{
15502 my ($TypeChanges, $TargetPriority, $Level) = @_;
15503 my $Type_Problems_Count = 0;
15504 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15505 {
15506 my %Kinds_Target = ();
15507 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15508 {
15509 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15510 {
15511 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015512 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15513 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015514 if($Kinds_Target{$Kind}{$Target}) {
15515 next;
15516 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015517
15518 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15519 {
15520 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15521 { # select a problem with the highest priority
15522 next;
15523 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015524 }
15525 $Kinds_Target{$Kind}{$Target} = 1;
15526 $Type_Problems_Count += 1;
15527 }
15528 }
15529 }
15530 return $Type_Problems_Count;
15531}
15532
15533sub get_Summary($)
15534{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015535 my $Level = $_[0];
15536 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015537 $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 +040015538 %{$RESULT{$Level}} = (
15539 "Problems"=>0,
15540 "Warnings"=>0,
15541 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015542 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015543 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015544 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015545 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015546 {
15547 if(not defined $CompatRules{$Level}{$Kind})
15548 { # unknown rule
15549 if(not $UnknownRules{$Level}{$Kind})
15550 { # only one warning
15551 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15552 $UnknownRules{$Level}{$Kind}=1;
15553 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015554 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015555 }
15556 }
15557 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015558 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15559 {
15560 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15561 {
15562 if(not defined $CompatRules{$Level}{$Kind})
15563 { # unknown rule
15564 if(not $UnknownRules{$Level}{$Kind})
15565 { # only one warning
15566 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15567 $UnknownRules{$Level}{$Kind}=1;
15568 }
15569 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15570 }
15571 }
15572 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015573 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015574 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015575 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015576 {
15577 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15578 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015579 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015580 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015581 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015582 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015583 $Added += 1;
15584 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015585 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015586 {
15587 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015588 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015589 }
15590 else
15591 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015592 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015593 $I_Other += 1;
15594 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015595 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015596 $I_Problems_High += 1;
15597 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015598 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015599 $I_Problems_Medium += 1;
15600 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015601 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015602 $I_Problems_Low += 1;
15603 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015604 if(($Severity ne "Low" or $StrictCompat)
15605 and $Severity ne "Safe") {
15606 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015607 }
15608 }
15609 }
15610 }
15611 }
15612 }
15613 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015614 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015615 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015616 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015617 {
15618 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15619 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015620 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015621 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015622 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15623 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015624 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015625 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15626
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015627 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015628 { # select a problem with the highest priority
15629 next;
15630 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015631
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015632 if(($Severity ne "Low" or $StrictCompat)
15633 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015634 {
15635 if(defined $TotalAffected{$Level}{$Interface})
15636 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015637 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15638 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015639 }
15640 }
15641 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015642 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015643 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015644 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015645
15646 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15647
15648 if($MaxSeverity)
15649 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015650 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15651 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015652 }
15653 }
15654 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015655 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015656 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015657 }
15658 }
15659 }
15660 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015661
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015662 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15663 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15664 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15665 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015666
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015667 %TypeChanges = (); # free memory
15668
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015669 if($CheckObjectsOnly)
15670 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015671 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015672 }
15673 else
15674 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015675 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015676 if($ExtendedCheck)
15677 { # don't count external_func_0 for constants
15678 $SCount-=1;
15679 }
15680 if($SCount)
15681 {
15682 my %Weight = (
15683 "High" => 100,
15684 "Medium" => 50,
15685 "Low" => 25
15686 );
15687 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015688 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015689 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015690 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015691 }
15692 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015693 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015694 }
15695 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015696 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15697 if($RESULT{$Level}{"Affected"}>=100) {
15698 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015699 }
15700
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015701 $RESULT{$Level}{"Problems"} += $Removed;
15702 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015703 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015704 if($StrictCompat) {
15705 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15706 }
15707 else {
15708 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15709 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015710
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015711 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015712 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015713 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015714 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015715 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015716 if($Severity eq "Safe")
15717 {
15718 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015719 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015720 elsif($Severity eq "Low")
15721 {
15722 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015723 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015724 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015725 }
15726
15727 if($C_Problems_Low)
15728 {
15729 if($StrictCompat) {
15730 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15731 }
15732 else {
15733 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015734 }
15735 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015736 if($RESULT{$Level}{"Problems"}
15737 and $RESULT{$Level}{"Affected"}) {
15738 $RESULT{$Level}{"Verdict"} = "incompatible";
15739 }
15740 else {
15741 $RESULT{$Level}{"Verdict"} = "compatible";
15742 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015743
15744 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15745 if(not $TotalTypes)
15746 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015747 $TotalTypes = keys(%{$TName_Tid{1}});
15748 }
15749
15750 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15751 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15752
15753 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15754
15755 if($ReportFormat eq "xml")
15756 { # XML
15757 # test info
15758 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15759 $TestInfo .= " <version1>\n";
15760 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015761 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015762 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15763 $TestInfo .= " </version1>\n";
15764
15765 $TestInfo .= " <version2>\n";
15766 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015767 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015768 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15769 $TestInfo .= " </version2>\n";
15770 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15771
15772 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015773 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015774 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015775 $TestResults .= " <headers>\n";
15776 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15777 {
15778 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15779 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15780 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15781 }
15782 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015783 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015784
15785 if(my @Sources = keys(%{$Registered_Sources{1}}))
15786 {
15787 $TestResults .= " <sources>\n";
15788 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15789 {
15790 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15791 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15792 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15793 }
15794 $TestResults .= " </sources>\n";
15795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015796
15797 $TestResults .= " <libs>\n";
15798 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15799 {
15800 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15801 $TestResults .= " <name>$Library</name>\n";
15802 }
15803 $TestResults .= " </libs>\n";
15804
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015805 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015806 $TestResults .= " <types>".$TotalTypes."</types>\n";
15807
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015808 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15809 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015810 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15811
15812 # problem summary
15813 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15814 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15815
15816 $Problem_Summary .= " <problems_with_types>\n";
15817 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15818 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15819 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15820 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15821 $Problem_Summary .= " </problems_with_types>\n";
15822
15823 $Problem_Summary .= " <problems_with_symbols>\n";
15824 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15825 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15826 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015827 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015828 $Problem_Summary .= " </problems_with_symbols>\n";
15829
15830 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015831 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015832 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015833
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015834 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15835
15836 return ($TestInfo.$TestResults.$Problem_Summary, "");
15837 }
15838 else
15839 { # HTML
15840 # test info
15841 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015842 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015843 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetTitle</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015844
15845 my (@VInf1, @VInf2, $AddTestInfo) = ();
15846 if($Arch1 ne "unknown"
15847 and $Arch2 ne "unknown")
15848 { # CPU arch
15849 if($Arch1 eq $Arch2)
15850 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015851 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015852 }
15853 else
15854 { # go to the version number
15855 push(@VInf1, showArch($Arch1));
15856 push(@VInf2, showArch($Arch2));
15857 }
15858 }
15859 if($GccV1 ne "unknown"
15860 and $GccV2 ne "unknown"
15861 and $OStarget ne "windows")
15862 { # GCC version
15863 if($GccV1 eq $GccV2)
15864 { # go to the separate section
15865 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15866 }
15867 else
15868 { # go to the version number
15869 push(@VInf1, "gcc ".$GccV1);
15870 push(@VInf2, "gcc ".$GccV2);
15871 }
15872 }
15873 # show long version names with GCC version and CPU architecture name (if different)
15874 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15875 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15876 $TestInfo .= $AddTestInfo;
15877 #if($COMMON_LANGUAGE{1}) {
15878 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15879 #}
15880 if($ExtendedCheck) {
15881 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15882 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015883 if($JoinReport)
15884 {
15885 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015886 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015887 }
15888 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015889 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015890 }
15891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015892 $TestInfo .= "</table>\n";
15893
15894 # test results
15895 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015896 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015897
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030015898 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015899 {
15900 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15901 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15902 }
15903 elsif($CheckObjectsOnly) {
15904 $TestResults .= "<tr><th>Total Header Files</th><td>0&#160;(not&#160;analyzed)</td></tr>\n";
15905 }
15906
15907 if(my @Sources = keys(%{$Registered_Sources{1}}))
15908 {
15909 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15910 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15911 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015912
15913 if(not $ExtendedCheck)
15914 {
15915 my $Libs_Link = "0";
15916 $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 +040015917 $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 +040015918 }
15919
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015920 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015921
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015922 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015923 if($JoinReport) {
15924 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15925 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015926 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015927 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015928 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15929 }
15930 else {
15931 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15932 }
15933 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015934 $TestResults .= "</table>\n";
15935
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015936 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015937 # problem summary
15938 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015939 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015940 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15941
15942 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015943 if($Added>0)
15944 {
15945 if($JoinReport) {
15946 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15947 }
15948 else {
15949 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15950 }
15951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015952 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015953 $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 +040015954
15955 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015956 if($Removed>0)
15957 {
15958 if($JoinReport) {
15959 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15960 }
15961 else {
15962 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
15963 }
15964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015965 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015966 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
15967 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015968
15969 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015970 $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 +040015971 $TH_Link = "n/a" if($CheckObjectsOnly);
15972 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015973 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
15974 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015975
15976 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015977 $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 +040015978 $TM_Link = "n/a" if($CheckObjectsOnly);
15979 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015980 $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 +040015981
15982 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015983 $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 +040015984 $TL_Link = "n/a" if($CheckObjectsOnly);
15985 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015986 $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 +040015987
15988 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015989 $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 +040015990 $IH_Link = "n/a" if($CheckObjectsOnly);
15991 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015992 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
15993 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015994
15995 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015996 $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 +040015997 $IM_Link = "n/a" if($CheckObjectsOnly);
15998 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015999 $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 +040016000
16001 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016002 $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 +040016003 $IL_Link = "n/a" if($CheckObjectsOnly);
16004 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016005 $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 +040016006
16007 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016008 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16009 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016010 }
16011 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016012 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016013 $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 +040016014
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016015 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016016 if($T_Other and not $CheckObjectsOnly)
16017 {
16018 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016019 $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 +040016020 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016021
16022 if($I_Other and not $CheckObjectsOnly)
16023 {
16024 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016025 $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 +040016026 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016027
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016028 if($C_Other and not $CheckObjectsOnly)
16029 {
16030 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16031 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
16032 }
16033
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016034 $META_DATA .= "tool_version:$TOOL_VERSION";
16035 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016036 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016037 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16038 }
16039}
16040
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016041sub getStyle($$$)
16042{
16043 my ($Subj, $Act, $Num) = @_;
16044 my %Style = (
16045 "A"=>"new",
16046 "R"=>"failed",
16047 "S"=>"passed",
16048 "L"=>"warning",
16049 "M"=>"failed",
16050 "H"=>"failed"
16051 );
16052 if($Num>0) {
16053 return " class='".$Style{$Act}."'";
16054 }
16055 return "";
16056}
16057
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016058sub show_number($)
16059{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016060 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016061 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016062 my $Num = cut_off_number($_[0], 2, 0);
16063 if($Num eq "0")
16064 {
16065 foreach my $P (3 .. 7)
16066 {
16067 $Num = cut_off_number($_[0], $P, 1);
16068 if($Num ne "0") {
16069 last;
16070 }
16071 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016072 }
16073 if($Num eq "0") {
16074 $Num = $_[0];
16075 }
16076 return $Num;
16077 }
16078 return $_[0];
16079}
16080
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016081sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016082{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016083 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016084 if($num!~/\./)
16085 {
16086 $num .= ".";
16087 foreach (1 .. $digs_to_cut-1) {
16088 $num .= "0";
16089 }
16090 }
16091 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16092 {
16093 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16094 $num .= "0";
16095 }
16096 }
16097 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16098 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16099 }
16100 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016101 if($z) {
16102 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16103 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016104 return $num;
16105}
16106
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016107sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016108{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016109 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016110 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016111
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016112 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016113 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16114 {
16115 my $Header = $Constants{1}{$Constant}{"Header"};
16116 if(not $Header)
16117 { # added
16118 $Header = $Constants{2}{$Constant}{"Header"}
16119 }
16120
16121 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16122 {
16123 if(not defined $CompatRules{$Level}{$Kind}) {
16124 next;
16125 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016126 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016127 next;
16128 }
16129 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16130 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016131 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016132
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016133 if($ReportFormat eq "xml")
16134 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016135 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016136 {
16137 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016138 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016139 {
16140 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016141 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16142 {
16143 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16144 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16145 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016146
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016147 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16148 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16149 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016150 if($Overcome) {
16151 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16152 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016153 $CHANGED_CONSTANTS .= " </problem>\n";
16154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016155 $CHANGED_CONSTANTS .= " </constant>\n";
16156 }
16157 $CHANGED_CONSTANTS .= " </header>\n";
16158 }
16159 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16160 }
16161 else
16162 { # HTML
16163 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016164 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016165 {
16166 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016167 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016168 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016169 my $Report = "";
16170
16171 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16172 {
16173 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16174 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16175 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16176 $Number += 1;
16177 }
16178 if($Report)
16179 {
16180 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16181 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16182 $Report = insertIDs($Report);
16183 }
16184 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016185 }
16186 $CHANGED_CONSTANTS .= "<br/>\n";
16187 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016188 if($CHANGED_CONSTANTS)
16189 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016190 my $Title = "Problems with Constants, $TargetSeverity Severity";
16191 if($TargetSeverity eq "Safe")
16192 { # Safe Changes
16193 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016194 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016195 $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 +040016196 }
16197 }
16198 return $CHANGED_CONSTANTS;
16199}
16200
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016201sub getTitle($$$)
16202{
16203 my ($Header, $Library, $NameSpace) = @_;
16204 my $Title = "";
16205 if($Library and $Library!~/\.\w+\Z/) {
16206 $Library .= " (.$LIB_EXT)";
16207 }
16208 if($Header and $Library)
16209 {
16210 $Title .= "<span class='h_name'>$Header</span>";
16211 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16212 }
16213 elsif($Library) {
16214 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16215 }
16216 elsif($Header) {
16217 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16218 }
16219 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016220 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016221 }
16222 return $Title;
16223}
16224
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016225sub get_Report_Added($)
16226{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016227 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016228 my $ADDED_INTERFACES = "";
16229 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016230 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016231 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016232 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016233 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016234 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016235 {
16236 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16237 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016238 if($Level eq "Source" and $ReportFormat eq "html")
16239 { # do not show library name in HTML report
16240 $DyLib = "";
16241 }
16242 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016243 }
16244 }
16245 }
16246 if($ReportFormat eq "xml")
16247 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016248 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016249 {
16250 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016251 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016252 {
16253 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016254 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016255 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16256 }
16257 $ADDED_INTERFACES .= " </library>\n";
16258 }
16259 $ADDED_INTERFACES .= " </header>\n";
16260 }
16261 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16262 }
16263 else
16264 { # HTML
16265 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016266 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016267 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016268 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016269 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016270 my %NameSpaceSymbols = ();
16271 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016272 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016273 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016274 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016275 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016276 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16277 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016278 foreach my $Interface (@SortedInterfaces)
16279 {
16280 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016281 my $Signature = get_Signature($Interface, 2);
16282 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016283 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016284 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016285 if($Interface=~/\A(_Z|\?)/)
16286 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016287 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016288 $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 +040016289 }
16290 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016291 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016292 }
16293 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016294 else
16295 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016296 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016297 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016298 }
16299 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016300 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016301 }
16302 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016303 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016304 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016306 }
16307 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016308 if($ADDED_INTERFACES)
16309 {
16310 my $Anchor = "<a name='Added'></a>";
16311 if($JoinReport) {
16312 $Anchor = "<a name='".$Level."_Added'></a>";
16313 }
16314 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016315 }
16316 }
16317 return $ADDED_INTERFACES;
16318}
16319
16320sub get_Report_Removed($)
16321{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016322 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016323 my $REMOVED_INTERFACES = "";
16324 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016325 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016326 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016327 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016328 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016329 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016330 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016331 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16332 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016333 if($Level eq "Source" and $ReportFormat eq "html")
16334 { # do not show library name in HTML report
16335 $DyLib = "";
16336 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016337 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016338 }
16339 }
16340 }
16341 if($ReportFormat eq "xml")
16342 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016343 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016344 {
16345 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016346 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016347 {
16348 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016349 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16350 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016351 }
16352 $REMOVED_INTERFACES .= " </library>\n";
16353 }
16354 $REMOVED_INTERFACES .= " </header>\n";
16355 }
16356 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16357 }
16358 else
16359 { # HTML
16360 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016361 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016362 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016363 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016364 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016365 my %NameSpaceSymbols = ();
16366 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016367 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016368 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016369 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016370 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016371 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16372 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016373 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016374 {
16375 $Removed_Number += 1;
16376 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016377 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016378 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016379 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016380 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016381 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016382 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016383 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016384 $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 +040016385 }
16386 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016387 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016388 }
16389 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016390 else
16391 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016392 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016393 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016394 }
16395 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016396 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016397 }
16398 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016399 }
16400 }
16401 $REMOVED_INTERFACES .= "<br/>\n";
16402 }
16403 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016404 if($REMOVED_INTERFACES)
16405 {
16406 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16407 if($JoinReport) {
16408 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16409 }
16410 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016411 }
16412 }
16413 return $REMOVED_INTERFACES;
16414}
16415
16416sub getXmlParams($$)
16417{
16418 my ($Content, $Problem) = @_;
16419 return "" if(not $Content or not $Problem);
16420 my %XMLparams = ();
16421 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16422 {
16423 my $Macro = "\@".lc($Attr);
16424 if($Content=~/\Q$Macro\E/) {
16425 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16426 }
16427 }
16428 my @PString = ();
16429 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016430 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016431 }
16432 if(@PString) {
16433 return " ".join(" ", @PString);
16434 }
16435 else {
16436 return "";
16437 }
16438}
16439
16440sub addMarkup($)
16441{
16442 my $Content = $_[0];
16443 # auto-markup
16444 $Content=~s/\n[ ]*//; # spaces
16445 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16446 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016447 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016448 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16449 if($Content=~/\ANOTE:/)
16450 { # notes
16451 $Content=~s!(NOTE):!<b>$1</b>:!g;
16452 }
16453 else {
16454 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16455 }
16456 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16457 my @Keywords = (
16458 "void",
16459 "const",
16460 "static",
16461 "restrict",
16462 "volatile",
16463 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016464 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016465 );
16466 my $MKeys = join("|", @Keywords);
16467 foreach (@Keywords) {
16468 $MKeys .= "|non-".$_;
16469 }
16470 $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 +040016471
16472 # Markdown
16473 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16474 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016475 return $Content;
16476}
16477
16478sub applyMacroses($$$$)
16479{
16480 my ($Level, $Kind, $Content, $Problem) = @_;
16481 return "" if(not $Content or not $Problem);
16482 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16483 $Content = addMarkup($Content);
16484 # macros
16485 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16486 {
16487 my $Macro = "\@".lc($Attr);
16488 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016489 if(not defined $Value
16490 or $Value eq "") {
16491 next;
16492 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016493 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016494 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016495 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
16496 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016497 $Value = black_name($Value);
16498 }
16499 elsif($Value=~/\s/) {
16500 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16501 }
16502 elsif($Value=~/\A\d+\Z/
16503 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16504 { # bits to bytes
16505 if($Value % $BYTE_SIZE)
16506 { # bits
16507 if($Value==1) {
16508 $Value = "<b>".$Value."</b> bit";
16509 }
16510 else {
16511 $Value = "<b>".$Value."</b> bits";
16512 }
16513 }
16514 else
16515 { # bytes
16516 $Value /= $BYTE_SIZE;
16517 if($Value==1) {
16518 $Value = "<b>".$Value."</b> byte";
16519 }
16520 else {
16521 $Value = "<b>".$Value."</b> bytes";
16522 }
16523 }
16524 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016525 else
16526 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016527 $Value = "<b>".htmlSpecChars($Value)."</b>";
16528 }
16529 $Content=~s/\Q$Macro\E/$Value/g;
16530 }
16531
16532 if($Content=~/(\A|[^\@\w])\@\w/)
16533 {
16534 if(not $IncompleteRules{$Level}{$Kind})
16535 { # only one warning
16536 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16537 $IncompleteRules{$Level}{$Kind} = 1;
16538 }
16539 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016540 return $Content;
16541}
16542
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016543sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016544{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016545 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016546 my $INTERFACE_PROBLEMS = "";
16547 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016548
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016549 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016550 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016551 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16552 if($SV and defined $CompatProblems{$Level}{$SN}) {
16553 next;
16554 }
16555 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016556 {
16557 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016558 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016559 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016560 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16561 my $DyLib = $Symbol_Library{1}{$Symbol};
16562 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016563 { # Symbol with Version
16564 $DyLib = $Symbol_Library{1}{$VSym};
16565 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016566 if(not $DyLib)
16567 { # const global data
16568 $DyLib = "";
16569 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016570 if($Level eq "Source" and $ReportFormat eq "html")
16571 { # do not show library name in HTML report
16572 $DyLib = "";
16573 }
16574 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16575 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016576 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016577 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16578 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016579 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016580 }
16581 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016582 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16583 {
16584 delete($SymbolChanges{$Symbol}{$Kind});
16585 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016586 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016587 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016588 }
16589 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016590 if(not keys(%{$SymbolChanges{$Symbol}})) {
16591 delete($SymbolChanges{$Symbol});
16592 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016593 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016594
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016595 if($ReportFormat eq "xml")
16596 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016597 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016598 {
16599 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016600 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016601 {
16602 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016603 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16604 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016605 {
16606 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16607 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16608 {
16609 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16610 {
16611 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016612 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016613
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016614 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16615 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16616 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16617 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16618 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016619 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16620 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16621 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016622 $INTERFACE_PROBLEMS .= " </problem>\n";
16623 }
16624 }
16625 $INTERFACE_PROBLEMS .= " </symbol>\n";
16626 }
16627 $INTERFACE_PROBLEMS .= " </library>\n";
16628 }
16629 $INTERFACE_PROBLEMS .= " </header>\n";
16630 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016631 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016632 }
16633 else
16634 { # HTML
16635 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016636 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016637 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016638 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016639 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016640 my (%NameSpaceSymbols, %NewSignature) = ();
16641 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016642 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016643 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016644 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016645 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016646 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016647 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 +040016648 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016649 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016650 my $Signature = get_Signature($Symbol, 1);
16651 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016652 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016653 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016654 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016655 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016656 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016657 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016658 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016659 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016660 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016661 }
16662 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16663 {
16664 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016665 $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 +040016666 $ProblemNum += 1;
16667 $ProblemsNum += 1;
16668 }
16669 }
16670 }
16671 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016672 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016673 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016674 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016675 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016676 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016677 }
16678 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016679 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016680 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016681 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16682 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16683 if($NewSignature{$Symbol})
16684 { # argument list changed to
16685 $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 +040016686 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016687 if($Symbol=~/\A(_Z|\?)/) {
16688 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16689 }
16690 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16691 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016692 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016693 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016694 }
16695 }
16696 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016697 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016698 }
16699 }
16700 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016701
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016702 if($INTERFACE_PROBLEMS)
16703 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016704 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16705 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16706 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016707 { # Safe Changes
16708 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016709 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016710 $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 +040016711 }
16712 }
16713 return $INTERFACE_PROBLEMS;
16714}
16715
16716sub get_Report_TypeProblems($$)
16717{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016718 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016719 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016720 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016721
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016722 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016723 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016724 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016725 {
16726 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16727 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016728 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016729 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016730 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016731 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016732 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016733
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016734 if($Severity eq "Safe"
16735 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016736 next;
16737 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016738
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016739 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16740 {
16741 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16742 { # select a problem with the highest priority
16743 next;
16744 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016745 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016746
16747 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016748 }
16749 }
16750 }
16751 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016752
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016753 my %Kinds_Locations = ();
16754 foreach my $TypeName (keys(%TypeChanges))
16755 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016756 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016757 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16758 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016759 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016760 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016761 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016762 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016763 { # other priority
16764 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16765 next;
16766 }
16767 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16768 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016769 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016770 { # duplicate target
16771 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16772 next;
16773 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016774 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016775 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016776 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016777 }
16778 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16779 delete($TypeChanges{$TypeName}{$Kind});
16780 }
16781 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016782 if(not keys(%{$TypeChanges{$TypeName}})) {
16783 delete($TypeChanges{$TypeName});
16784 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016785 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016786
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016787 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 +040016788 if($ReportFormat eq "xml")
16789 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016790 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016791 {
16792 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016793 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016794 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016795 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016796 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16797 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016798 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016799 {
16800 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16801 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16802 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16803 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16804 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16805 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016806 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16807 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016809 $TYPE_PROBLEMS .= " </problem>\n";
16810 }
16811 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016812 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016813 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016814 $TYPE_PROBLEMS .= showVTables($TypeName);
16815 }
16816 $TYPE_PROBLEMS .= " </type>\n";
16817 }
16818 $TYPE_PROBLEMS .= " </header>\n";
16819 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016820 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016821 }
16822 else
16823 { # HTML
16824 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016825 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016826 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016827 my (%NameSpace_Type) = ();
16828 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016829 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016830 }
16831 foreach my $NameSpace (sort keys(%NameSpace_Type))
16832 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016833 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016834 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 +040016835 foreach my $TypeName (@SortedTypes)
16836 {
16837 my $ProblemNum = 1;
16838 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016839
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016840 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16841 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016842 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016843 {
16844 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16845 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16846 {
16847 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
16848 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16849 $ProblemNum += 1;
16850 $ProblemsNum += 1;
16851 }
16852 }
16853 }
16854 $ProblemNum -= 1;
16855 if($TYPE_REPORT)
16856 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016857 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016858 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016859 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016860 $ShowVTables = showVTables($TypeName);
16861 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016862
16863 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016864 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16865 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16866 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16867 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016868 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016869 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016870 }
16871 }
16872 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016873 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016874 }
16875 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016876
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016877 if($TYPE_PROBLEMS)
16878 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016879 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16880 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016881 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016882 { # Safe Changes
16883 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016884 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016885 $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 +040016886 }
16887 }
16888 return $TYPE_PROBLEMS;
16889}
16890
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016891sub show_Type($$$)
16892{
16893 my ($Name, $Html, $LibVersion) = @_;
16894 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16895 $TType = lc($TType);
16896 if($TType=~/struct|union|enum/) {
16897 $Name=~s/\A\Q$TType\E //g;
16898 }
16899 if($Html) {
16900 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16901 }
16902 else {
16903 $Name = $TType." ".$Name;
16904 }
16905 return $Name;
16906}
16907
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016908sub get_Anchor($$$)
16909{
16910 my ($Kind, $Level, $Severity) = @_;
16911 if($JoinReport)
16912 {
16913 if($Severity eq "Safe") {
16914 return "Other_".$Level."_Changes_In_".$Kind."s";
16915 }
16916 else {
16917 return $Kind."_".$Level."_Problems_".$Severity;
16918 }
16919 }
16920 else
16921 {
16922 if($Severity eq "Safe") {
16923 return "Other_Changes_In_".$Kind."s";
16924 }
16925 else {
16926 return $Kind."_Problems_".$Severity;
16927 }
16928 }
16929}
16930
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016931sub showVTables($)
16932{
16933 my $TypeName = $_[0];
16934 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016935 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016936 if(defined $Type1{"VTable"}
16937 and keys(%{$Type1{"VTable"}}))
16938 {
16939 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016940 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016941 if(defined $Type2{"VTable"}
16942 and keys(%{$Type2{"VTable"}}))
16943 {
16944 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
16945 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016946 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016947 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016948 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
16949 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016950 }
16951 my $VTABLES = "";
16952 if($ReportFormat eq "xml")
16953 { # XML
16954 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016955 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016956 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016957 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016958 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
16959 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016960 $VTABLES .= " </entry>\n";
16961 }
16962 $VTABLES .= " </vtable>\n\n";
16963 }
16964 else
16965 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016966 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016967 $VTABLES .= "<tr><th>Offset</th>";
16968 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016969 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016970 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016971 {
16972 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016973 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016974 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016975 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016976 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016977 $Color1 = " class='failed'";
16978 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016979 }
16980 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016981 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016982 }
16983 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016984 $VTABLES .= "<tr><th>".$Index."</th>\n";
16985 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
16986 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016987 }
16988 $VTABLES .= "</table><br/>\n";
16989 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016990 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016991 }
16992 return $VTABLES;
16993 }
16994 }
16995 return "";
16996}
16997
16998sub simpleVEntry($)
16999{
17000 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017001 if(not defined $VEntry
17002 or $VEntry eq "") {
17003 return "";
17004 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017005
17006 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017007 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17008 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17009 if($VEntry=~/\A_ZThn.+\Z/) {
17010 $VEntry = "non-virtual thunk";
17011 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017012 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017013 # support for old GCC versions
17014 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17015 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17016 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017017 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17018 return $VEntry;
17019}
17020
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017021sub adjustParamPos($$$)
17022{
17023 my ($Pos, $Symbol, $LibVersion) = @_;
17024 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17025 {
17026 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17027 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17028 {
17029 return $Pos-1;
17030 }
17031
17032 return $Pos;
17033 }
17034
17035 return undef;
17036}
17037
17038sub getParamPos($$$)
17039{
17040 my ($Name, $Symbol, $LibVersion) = @_;
17041
17042 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17043 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17044 {
17045 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17046 foreach (keys(%{$Info->{"Param"}}))
17047 {
17048 if($Info->{"Param"}{$_}{"name"} eq $Name)
17049 {
17050 return $_;
17051 }
17052 }
17053 }
17054
17055 return undef;
17056}
17057
17058sub getParamName($)
17059{
17060 my $Loc = $_[0];
17061 $Loc=~s/\->.*//g;
17062 return $Loc;
17063}
17064
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017065sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017066{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017067 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017068 my $LIMIT = 10;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017069
17070 if(defined $AffectLimit)
17071 {
17072 $LIMIT = $AffectLimit;
17073 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017074
17075 my %SymSel = ();
17076 my %SymLocKind = ();
17077
17078 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017079 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017080 if(index($Symbol, "_Z")==0
17081 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017082 { # duplicated problems for C2 constructors, D2 and D0 destructors
17083 next;
17084 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017085
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017086 foreach my $Kind (sort keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017087 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017088 if(not defined $CompatProblems{$Level}{$Symbol}
17089 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17090 next;
17091 }
17092
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017093 foreach my $Loc (sort keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017094 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017095 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017096 next;
17097 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017098
17099 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17100 if($Level eq "Source")
17101 { # remove symbol version
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017102 $Symbol = $SN;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017103 }
17104
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017105 if($SV and defined $CompatProblems{$Level}{$SN}
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017106 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017107 { # duplicated problems for versioned symbols
17108 next;
17109 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017110
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017111 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017112 if($Type_Name ne $Target_TypeName) {
17113 next;
17114 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017115
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017116 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017117 }
17118 }
17119 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017120
17121 foreach my $Symbol (sort keys(%SymLocKind))
17122 {
17123 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17124 {
17125 foreach my $Kind (keys(%{$SymLocKind{$Symbol}{$Loc}}))
17126 {
17127 $SymSel{$Symbol}{"Loc"} = $Loc;
17128 $SymSel{$Symbol}{"Kind"} = $Kind;
17129
17130 last LOOP;
17131 }
17132 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017133 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017134
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017135 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017136 my $Num = 0;
17137
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017138 if($ReportFormat eq "xml")
17139 { # XML
17140 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017141
17142 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017143 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017144 my $PName = getParamName($Loc);
17145 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17146
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017147 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017148 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017149 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017150 $Target .= " param=\"$PName\"";
17151 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017152 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017153 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017154 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017155 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017156 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017157 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017158 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017159
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017160 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017161 $Target .= " field=\"$1\"";
17162 }
17163
17164 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017165 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017166 $Affected .= " </symbol>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017167
17168 if($Num>$LIMIT) {
17169 last LOOP;
17170 }
17171
17172 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017173 }
17174 $Affected .= " </affected>\n";
17175 }
17176 else
17177 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017178 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017179 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017180 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17181 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017182 my $PName = getParamName($SymSel{$Symbol}{"Loc"});
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017183 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17184
17185 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>";
17186 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
17187
17188 if($Num>$LIMIT) {
17189 last;
17190 }
17191
17192 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017193 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017194
17195 if(keys(%SymSel)>$LIMIT) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017196 $Affected .= " ...<br/>"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017197 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017198
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017199 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017200 if($Affected)
17201 {
17202 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017203 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymSel).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017204 }
17205 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017206
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017207 return $Affected;
17208}
17209
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017210sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017211{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017212 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017213 if($L2=~/\A(retval|this)\b/
17214 and $L1!~/\A(retval|this)\b/)
17215 {
17216 if($L1!~/\-\>/) {
17217 return 1;
17218 }
17219 elsif($L2=~/\-\>/) {
17220 return 1;
17221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017222 }
17223 return 0;
17224}
17225
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017226sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017227{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017228 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017229
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017230 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017231
17232 my $Location_I = $Location;
17233 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17234
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017235 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017236
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017237 if($Kind eq "Overridden_Virtual_Method"
17238 or $Kind eq "Overridden_Virtual_Method_B") {
17239 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17240 }
17241 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17242 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017243 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17244
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017245 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17246 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017247 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17248 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17249
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017250 if($ClassName eq $Problem{"Type_Name"}) {
17251 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17252 }
17253 else {
17254 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17255 }
17256 }
17257 else
17258 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017259 my $TypeID = undef;
17260
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017261 if($Location=~/retval/)
17262 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017263 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017264 push(@Sentence, "Field \'".$Location."\' in return value");
17265 }
17266 else {
17267 push(@Sentence, "Return value");
17268 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017269
17270 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017271 }
17272 elsif($Location=~/this/)
17273 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017274 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017275 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17276 }
17277 else {
17278 push(@Sentence, "\'this\' pointer");
17279 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017280
17281 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017282 }
17283 else
17284 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017285
17286 my $PName = getParamName($Location);
17287 my $PPos = getParamPos($PName, $Symbol, 1);
17288
17289 if(index($Location, "->")!=-1) {
17290 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017291 }
17292 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017293 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017294 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017295 if($PName) {
17296 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017297 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017298
17299 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17300 }
17301
17302 if($Location!~/this/)
17303 {
17304 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017305 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017306 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017307 push(@Sentence, "(pointer)");
17308 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017309 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017310 push(@Sentence, "(reference)");
17311 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017312 }
17313 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017314
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017315 if($Location eq "this") {
17316 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17317 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017318 else
17319 {
17320 my $Location_T = $Location;
17321 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17322
17323 my $TypeID_Problem = $TypeID;
17324 if($Location_T) {
17325 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17326 }
17327
17328 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17329 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17330 }
17331 else {
17332 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017334 }
17335 }
17336 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017337 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017338 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 +040017339 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017340
17341 my $Sent = join(" ", @Sentence);
17342
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017343 $Sent=~s/->/./g;
17344
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017345 if($ReportFormat eq "xml")
17346 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017347 $Sent=~s/'//g;
17348 }
17349
17350 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017351}
17352
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017353sub getFieldType($$$)
17354{
17355 my ($Location, $TypeId, $LibVersion) = @_;
17356
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017357 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017358
17359 foreach my $Name (@Fields)
17360 {
17361 my %Info = get_BaseType($TypeId, $LibVersion);
17362
17363 foreach my $Pos (keys(%{$Info{"Memb"}}))
17364 {
17365 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17366 {
17367 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17368 last;
17369 }
17370 }
17371 }
17372
17373 return $TypeId;
17374}
17375
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017376sub get_XmlSign($$)
17377{
17378 my ($Symbol, $LibVersion) = @_;
17379 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17380 my $Report = "";
17381 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17382 {
17383 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017384 my $Type = $Info->{"Param"}{$Pos}{"type"};
17385 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017386 foreach my $Typedef (keys(%ChangedTypedef))
17387 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017388 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17389 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17390 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017391 }
17392 $Report .= " <param pos=\"$Pos\">\n";
17393 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017394 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017395 $Report .= " </param>\n";
17396 }
17397 if(my $Return = $Info->{"Return"})
17398 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017399 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017400 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017401 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017402 $Report .= " </retval>\n";
17403 }
17404 return $Report;
17405}
17406
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017407sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017408{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017409 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017410 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017411 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017412 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017413 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17414 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017415 next;
17416 }
17417 $Report .= " <symbol name=\"$Symbol\">\n";
17418 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017419 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017420 {
17421 if(defined $CompleteSignature{1}{$Symbol}
17422 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17423 {
17424 $P1 = get_XmlSign($Symbol, 1);
17425 $S1 = get_Signature($Symbol, 1);
17426 }
17427 elsif($Symbol=~/\A(_Z|\?)/) {
17428 $S1 = $tr_name{$Symbol};
17429 }
17430 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017431 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017432 {
17433 if(defined $CompleteSignature{2}{$Symbol}
17434 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17435 {
17436 $P2 = get_XmlSign($Symbol, 2);
17437 $S2 = get_Signature($Symbol, 2);
17438 }
17439 elsif($Symbol=~/\A(_Z|\?)/) {
17440 $S2 = $tr_name{$Symbol};
17441 }
17442 }
17443 if($S1)
17444 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017445 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017446 $Report .= $P1;
17447 $Report .= " </old>\n";
17448 }
17449 if($S2 and $S2 ne $S1)
17450 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017451 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017452 $Report .= $P2;
17453 $Report .= " </new>\n";
17454 }
17455 $Report .= " </symbol>\n";
17456 }
17457 $Report .= "</symbols_info>\n";
17458 return $Report;
17459}
17460
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017461sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017462{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017463 my ($Level, $Report) = @_;
17464 if($ReportFormat eq "xml") {
17465 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017466 }
17467 if($StdOut)
17468 { # --stdout option
17469 print STDOUT $Report;
17470 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017471 else
17472 {
17473 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017474 mkpath(get_dirname($RPath));
17475
17476 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17477 print REPORT $Report;
17478 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017479 }
17480}
17481
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017482sub getReport($)
17483{
17484 my $Level = $_[0];
17485 if($ReportFormat eq "xml")
17486 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017487 if($Level eq "Join")
17488 {
17489 my $Report = "<reports>\n";
17490 $Report .= getReport("Binary");
17491 $Report .= getReport("Source");
17492 $Report .= "</reports>\n";
17493 return $Report;
17494 }
17495 else
17496 {
17497 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17498 my ($Summary, $MetaData) = get_Summary($Level);
17499 $Report .= $Summary."\n";
17500 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17501 $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 +040017502
17503 # additional symbols info (if needed)
17504 # $Report .= get_Report_SymbolsInfo($Level);
17505
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017506 $Report .= "</report>\n";
17507 return $Report;
17508 }
17509 }
17510 else
17511 { # HTML
17512 my $CssStyles = readModule("Styles", "Report.css");
17513 my $JScripts = readModule("Scripts", "Sections.js");
17514 if($Level eq "Join")
17515 {
17516 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17517 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017518 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
17519 my $Keywords = $TargetTitle.", compatibility, API, report";
17520 my $Description = "Compatibility report for the $TargetTitle $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017521 my ($BSummary, $BMetaData) = get_Summary("Binary");
17522 my ($SSummary, $SMetaData) = get_Summary("Source");
17523 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 +030017524 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017525 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017526 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17527 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017528 </div>";
17529 $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>";
17530 $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 +030017531 $Report .= getReportFooter("Double");
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017532 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017533 return $Report;
17534 }
17535 else
17536 {
17537 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017538 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17539 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17540 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 +040017541 if($Level eq "Binary")
17542 {
17543 if(getArch(1) eq getArch(2)
17544 and getArch(1) ne "unknown") {
17545 $Description .= " on ".showArch(getArch(1));
17546 }
17547 }
17548 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 +030017549 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017550 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17551 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17552 $Report .= get_SourceInfo();
17553 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017554 $Report .= getReportFooter("Single");
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017555 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017556 return $Report;
17557 }
17558 }
17559}
17560
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017561sub getLegend()
17562{
17563 return "<br/>
17564<table class='summary'>
17565<tr>
17566 <td class='new'>added</td>
17567 <td class='passed'>compatible</td>
17568</tr>
17569<tr>
17570 <td class='warning'>warning</td>
17571 <td class='failed'>incompatible</td>
17572</tr></table>\n";
17573}
17574
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017575sub createReport()
17576{
17577 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017578 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017579 writeReport("Join", getReport("Join"));
17580 }
17581 elsif($DoubleReport)
17582 { # default
17583 writeReport("Binary", getReport("Binary"));
17584 writeReport("Source", getReport("Source"));
17585 }
17586 elsif($BinaryOnly)
17587 { # --binary
17588 writeReport("Binary", getReport("Binary"));
17589 }
17590 elsif($SourceOnly)
17591 { # --source
17592 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017593 }
17594}
17595
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017596sub getReportFooter($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017597{
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017598 my $Type = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017599 my $Class = "footer";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017600
17601 if($Type eq "Double") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017602 $Class .= " double_report";
17603 }
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017604
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017605 my $Footer = "<div class=\'$Class\' align='right'><i>Generated on ".(localtime time);
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017606 $Footer .= " by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017607 $Footer .= "</i></div>";
17608 $Footer .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017609 return $Footer;
17610}
17611
17612sub get_Report_Problems($$)
17613{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017614 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017615
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017616 my $Report = get_Report_TypeProblems($Severity, $Level);
17617 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017618 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017619 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017620
17621 if($Severity eq "Low" or $Severity eq "Safe") {
17622 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017623 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017624
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017625 if($ReportFormat eq "html")
17626 {
17627 if($Report)
17628 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017629 if($JoinReport)
17630 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017631 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017632 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17633 }
17634 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017635 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017636 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017637 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017638 else
17639 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017640 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017641 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17642 }
17643 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017644 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017645 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017646 }
17647 }
17648 }
17649 return $Report;
17650}
17651
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017652sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017653{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017654 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17655 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17656 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17657 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017658 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17659 <meta name=\"keywords\" content=\"$Keywords\" />
17660 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017661 <title>
17662 $Title
17663 </title>
17664 <style type=\"text/css\">
17665 $Styles
17666 </style>
17667 <script type=\"text/javascript\" language=\"JavaScript\">
17668 <!--
17669 $Scripts
17670 -->
17671 </script>
17672 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017673}
17674
17675sub insertIDs($)
17676{
17677 my $Text = $_[0];
17678 while($Text=~/CONTENT_ID/)
17679 {
17680 if(int($Content_Counter)%2) {
17681 $ContentID -= 1;
17682 }
17683 $Text=~s/CONTENT_ID/c_$ContentID/;
17684 $ContentID += 1;
17685 $Content_Counter += 1;
17686 }
17687 return $Text;
17688}
17689
17690sub checkPreprocessedUnit($)
17691{
17692 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017693 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017694 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017695 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017696
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017697 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017698 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017699 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017700 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017701 chomp($Line);
17702 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017703 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017704 $CurHeader = path_format($1, $OSgroup);
17705 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017706 $CurClass = "";
17707
17708 if(index($CurHeader, $TMP_DIR)==0) {
17709 next;
17710 }
17711
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017712 if(substr($CurHeaderName, 0, 1) eq "<")
17713 { # <built-in>, <command-line>, etc.
17714 $CurHeaderName = "";
17715 $CurHeader = "";
17716 }
17717
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017718 if($ExtraInfo)
17719 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017720 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017721 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17722 }
17723 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017724 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017725 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017726 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017727 if($CurHeaderName)
17728 {
17729 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17730 and not $Registered_Headers{$Version}{$CurHeader})
17731 { # not a target
17732 next;
17733 }
17734 if(not is_target_header($CurHeaderName, 1)
17735 and not is_target_header($CurHeaderName, 2))
17736 { # user-defined header
17737 next;
17738 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017739 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017740 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017741
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017742 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017743 {
17744 my ($Name, $Value) = ($1, $2);
17745 if(not $Constants{$Version}{$Name}{"Access"})
17746 {
17747 $Constants{$Version}{$Name}{"Access"} = "public";
17748 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017749 if($CurHeaderName) {
17750 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17751 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017752 }
17753 }
17754 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17755 $Constants{$Version}{$1}{"Access"} = "private";
17756 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017757 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017758 else
17759 {
17760 if(defined $ExtraDump)
17761 {
17762 if($Line=~/(\w+)\s*\(/)
17763 { # functions
17764 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17765 }
17766 #elsif($Line=~/(\w+)\s*;/)
17767 #{ # data
17768 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17769 #}
17770 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17771 $CurClass = $2;
17772 }
17773 }
17774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017775 }
17776 close(PREPROC);
17777 foreach my $Constant (keys(%{$Constants{$Version}}))
17778 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017779 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17780 {
17781 delete($Constants{$Version}{$Constant});
17782 next;
17783 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017784 if(not $ExtraDump and ($Constant=~/_h\Z/i
17785 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017786 { # skip
17787 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017788 }
17789 else {
17790 delete($Constants{$Version}{$Constant}{"Access"});
17791 }
17792 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017793 if($Debug)
17794 {
17795 mkpath($DEBUG_PATH{$Version});
17796 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17797 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017798}
17799
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017800sub uncoverConstant($$)
17801{
17802 my ($LibVersion, $Constant) = @_;
17803 return "" if(not $LibVersion or not $Constant);
17804 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17805 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17806 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17807 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017808
17809 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017810 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017811 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17812 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017813 {
17814 push(@RecurConstant, $Constant);
17815 my $Uncovered = uncoverConstant($LibVersion, $Value);
17816 if($Uncovered ne "") {
17817 $Value = $Uncovered;
17818 }
17819 pop(@RecurConstant);
17820 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017821
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017822 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017823 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017824 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17825 }
17826 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17827}
17828
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017829sub simpleConstant($$)
17830{
17831 my ($LibVersion, $Value) = @_;
17832 if($Value=~/\W/)
17833 {
17834 my $Value_Copy = $Value;
17835 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17836 {
17837 my $Word = $1;
17838 if($Value!~/$Word\s*\(/)
17839 {
17840 my $Val = uncoverConstant($LibVersion, $Word);
17841 if($Val ne "")
17842 {
17843 $Value=~s/\b$Word\b/$Val/g;
17844 }
17845 }
17846 }
17847 }
17848 return $Value;
17849}
17850
17851sub computeValue($)
17852{
17853 my $Value = $_[0];
17854
17855 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17856 return $1;
17857 }
17858
17859 if($Value=~/\A[\d\-\+()]+\Z/) {
17860 return eval($Value);
17861 }
17862
17863 return $Value;
17864}
17865
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017866my %IgnoreConstant = map {$_=>1} (
17867 "VERSION",
17868 "VERSIONCODE",
17869 "VERNUM",
17870 "VERS_INFO",
17871 "PATCHLEVEL",
17872 "INSTALLPREFIX",
17873 "VBUILD",
17874 "VPATCH",
17875 "VMINOR",
17876 "BUILD_STRING",
17877 "BUILD_TIME",
17878 "PACKAGE_STRING",
17879 "PRODUCTION",
17880 "CONFIGURE_COMMAND",
17881 "INSTALLDIR",
17882 "BINDIR",
17883 "CONFIG_FILE_PATH",
17884 "DATADIR",
17885 "EXTENSION_DIR",
17886 "INCLUDE_PATH",
17887 "LIBDIR",
17888 "LOCALSTATEDIR",
17889 "SBINDIR",
17890 "SYSCONFDIR",
17891 "RELEASE",
17892 "SOURCE_ID",
17893 "SUBMINOR",
17894 "MINOR",
17895 "MINNOR",
17896 "MINORVERSION",
17897 "MAJOR",
17898 "MAJORVERSION",
17899 "MICRO",
17900 "MICROVERSION",
17901 "BINARY_AGE",
17902 "INTERFACE_AGE",
17903 "CORE_ABI",
17904 "PATCH",
17905 "COPYRIGHT",
17906 "TIMESTAMP",
17907 "REVISION",
17908 "PACKAGE_TAG",
17909 "PACKAGEDATE",
17910 "NUMVERSION",
17911 "Release",
17912 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017913);
17914
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017915sub constantFilter($$$)
17916{
17917 my ($Name, $Value, $Level) = @_;
17918
17919 if($Level eq "Binary")
17920 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017921 if($Name=~/_t\Z/)
17922 { # __malloc_ptr_t
17923 return 1;
17924 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017925 foreach (keys(%IgnoreConstant))
17926 {
17927 if($Name=~/(\A|_)$_(_|\Z)/)
17928 { # version
17929 return 1;
17930 }
17931 if(/\A[A-Z].*[a-z]\Z/)
17932 {
17933 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17934 { # version
17935 return 1;
17936 }
17937 }
17938 }
17939 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17940 { # version
17941 return 1;
17942 }
17943 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17944 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17945 return 1;
17946 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017947
17948 if($Value=~/\A["'].*['"]/i)
17949 { # string
17950 return 0;
17951 }
17952
17953 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17954 { # static int gcry_pth_init
17955 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017956 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017957 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017958 return 1;
17959 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017960 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017961 { # foo(p)
17962 return 1;
17963 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017964 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017965 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017966 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017967 return 1;
17968 }
17969 }
17970
17971 return 0;
17972}
17973
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017974sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017975{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017976 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017977 foreach my $Constant (keys(%{$Constants{1}}))
17978 {
17979 if($SkipConstants{1}{$Constant})
17980 { # skipped by the user
17981 next;
17982 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017983
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017984 if(my $Header = $Constants{1}{$Constant}{"Header"})
17985 {
17986 if(not is_target_header($Header, 1)
17987 and not is_target_header($Header, 2))
17988 { # user-defined header
17989 next;
17990 }
17991 }
17992 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017993 next;
17994 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017995
17996 my $Old_Value = uncoverConstant(1, $Constant);
17997
17998 if(constantFilter($Constant, $Old_Value, $Level))
17999 { # separate binary and source problems
18000 next;
18001 }
18002
18003 if(not defined $Constants{2}{$Constant}{"Value"})
18004 { # removed
18005 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18006 "Target"=>$Constant,
18007 "Old_Value"=>$Old_Value );
18008 next;
18009 }
18010
18011 if($Constants{2}{$Constant}{"Value"} eq "")
18012 { # empty value
18013 # TODO: implement a rule
18014 next;
18015 }
18016
18017 my $New_Value = uncoverConstant(2, $Constant);
18018
18019 my $Old_Value_Pure = $Old_Value;
18020 my $New_Value_Pure = $New_Value;
18021
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018022 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18023 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18024 $New_Value_Pure=~s/(\W)\s+/$1/g;
18025 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018026
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018027 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018028
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018029 if($New_Value_Pure ne $Old_Value_Pure)
18030 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018031 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18032 { # complex values
18033 next;
18034 }
18035 if(computeValue($Old_Value) eq computeValue($New_Value))
18036 { # expressions
18037 next;
18038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018039 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18040 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18041 next;
18042 }
18043 if($Old_Value eq "0" and $New_Value eq "NULL")
18044 { # 0 => NULL
18045 next;
18046 }
18047 if($Old_Value eq "NULL" and $New_Value eq "0")
18048 { # NULL => 0
18049 next;
18050 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018051 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018052 "Target"=>$Constant,
18053 "Old_Value"=>$Old_Value,
18054 "New_Value"=>$New_Value );
18055 }
18056 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018057
18058 foreach my $Constant (keys(%{$Constants{2}}))
18059 {
18060 if(not defined $Constants{1}{$Constant}{"Value"})
18061 {
18062 if($SkipConstants{2}{$Constant})
18063 { # skipped by the user
18064 next;
18065 }
18066
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018067 if(my $Header = $Constants{2}{$Constant}{"Header"})
18068 {
18069 if(not is_target_header($Header, 1)
18070 and not is_target_header($Header, 2))
18071 { # user-defined header
18072 next;
18073 }
18074 }
18075 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018076 next;
18077 }
18078
18079 my $New_Value = uncoverConstant(2, $Constant);
18080 if(not defined $New_Value or $New_Value eq "") {
18081 next;
18082 }
18083
18084 if(constantFilter($Constant, $New_Value, $Level))
18085 { # separate binary and source problems
18086 next;
18087 }
18088
18089 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18090 "Target"=>$Constant,
18091 "New_Value"=>$New_Value );
18092 }
18093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018094}
18095
18096sub convert_integer($)
18097{
18098 my $Value = $_[0];
18099 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018100 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018101 return hex($Value);
18102 }
18103 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018104 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018105 return oct($Value);
18106 }
18107 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018108 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018109 return oct($Value);
18110 }
18111 else {
18112 return $Value;
18113 }
18114}
18115
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018116sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018117{
18118 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018119 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018120 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018121 {
18122 if($LibVersion==1)
18123 {
18124 printMsg("WARNING", "checking headers only");
18125 $CheckHeadersOnly = 1;
18126 }
18127 else {
18128 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18129 }
18130 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018131
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018132 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018133 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018134 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018135
18136 if($CheckUndefined)
18137 {
18138 my %UndefinedLibs = ();
18139
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018140 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18141
18142 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018143 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018144 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018145 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018146 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018147 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018148 if($Symbol_Library{$LibVersion}{$Symbol}
18149 or $DepSymbol_Library{$LibVersion}{$Symbol})
18150 { # exported by target library
18151 next;
18152 }
18153 if(index($Symbol, '@')!=-1)
18154 { # exported default symbol version (@@)
18155 $Symbol=~s/\@/\@\@/;
18156 if($Symbol_Library{$LibVersion}{$Symbol}
18157 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18158 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018159 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018160 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018161 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18162 $UndefinedLibs{$Path} = 1;
18163 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018164 }
18165 }
18166 }
18167 if($ExtraInfo)
18168 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018169 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018170 {
18171 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018172 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018173 foreach (@Paths)
18174 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018175 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018176 my ($Dir, $Name) = separate_path($_);
18177
18178 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018179 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018180 }
18181
18182 $Name = parse_libname($Name, "name", $OStarget);
18183 $Name=~s/\Alib//;
18184
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018185 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018186 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018187
18188 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18189 {
18190 $LibString = " -L".esc($Dir).$LibString;
18191 }
18192
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018193 writeFile($ExtraInfo."/libs-string", $LibString);
18194 }
18195 }
18196 }
18197
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018198 if($ExtraInfo) {
18199 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18200 }
18201
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018202 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018203 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018204 if($#LibPaths!=-1)
18205 {
18206 if(not keys(%{$Symbol_Library{$LibVersion}}))
18207 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018208 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018209 printMsg("WARNING", "checking headers only");
18210 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018211 }
18212 }
18213 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018214
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018215 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018216 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018217}
18218
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018219my %Prefix_Lib_Map=(
18220 # symbols for autodetecting library dependencies (by prefix)
18221 "pthread_" => ["libpthread"],
18222 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18223 "cairo_" => ["libcairo"],
18224 "gtk_" => ["libgtk-x11-2.0"],
18225 "atk_" => ["libatk-1.0"],
18226 "gdk_" => ["libgdk-x11-2.0"],
18227 "gl" => ["libGL"],
18228 "glu" => ["libGLU"],
18229 "popt" => ["libpopt"],
18230 "Py" => ["libpython"],
18231 "jpeg_" => ["libjpeg"],
18232 "BZ2_" => ["libbz2"],
18233 "Fc" => ["libfontconfig"],
18234 "Xft" => ["libXft"],
18235 "SSL_" => ["libssl"],
18236 "sem_" => ["libpthread"],
18237 "snd_" => ["libasound"],
18238 "art_" => ["libart_lgpl_2"],
18239 "dbus_g" => ["libdbus-glib-1"],
18240 "GOMP_" => ["libgomp"],
18241 "omp_" => ["libgomp"],
18242 "cms" => ["liblcms"]
18243);
18244
18245my %Pattern_Lib_Map=(
18246 "SL[a-z]" => ["libslang"]
18247);
18248
18249my %Symbol_Lib_Map=(
18250 # symbols for autodetecting library dependencies (by name)
18251 "pow" => "libm",
18252 "fmod" => "libm",
18253 "sin" => "libm",
18254 "floor" => "libm",
18255 "cos" => "libm",
18256 "dlopen" => "libdl",
18257 "deflate" => "libz",
18258 "inflate" => "libz",
18259 "move_panel" => "libpanel",
18260 "XOpenDisplay" => "libX11",
18261 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018262 "clock_gettime" => "librt",
18263 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018264);
18265
18266sub find_SymbolLibs($$)
18267{
18268 my ($LibVersion, $Symbol) = @_;
18269
18270 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18271 { # debug symbols
18272 return ();
18273 }
18274
18275 my %Paths = ();
18276
18277 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18278 {
18279 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18280 $Paths{$Path} = 1;
18281 }
18282 }
18283
18284 if(my $SymbolPrefix = getPrefix($Symbol))
18285 {
18286 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18287 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18288 }
18289
18290 if(not keys(%Paths))
18291 {
18292 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18293 {
18294 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18295 {
18296 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18297 $Paths{$Path} = 1;
18298 }
18299 }
18300 }
18301 }
18302
18303 if(not keys(%Paths))
18304 {
18305 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18306 {
18307 if($Symbol=~/\A$Prefix/)
18308 {
18309 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18310 {
18311 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18312 $Paths{$Path} = 1;
18313 }
18314 }
18315 }
18316 }
18317 }
18318
18319 if(not keys(%Paths))
18320 {
18321 if($SymbolPrefix)
18322 { # try to find a library by symbol prefix
18323 if($SymbolPrefix eq "inotify" and
18324 index($Symbol, "\@GLIBC")!=-1)
18325 {
18326 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18327 $Paths{$Path} = 1;
18328 }
18329 }
18330 else
18331 {
18332 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18333 $Paths{$Path} = 1;
18334 }
18335 }
18336 }
18337 }
18338
18339 if(my @Paths = keys(%Paths)) {
18340 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18341 }
18342 }
18343 return keys(%Paths);
18344}
18345
18346sub get_LibPath_Prefix($$)
18347{
18348 my ($LibVersion, $Prefix) = @_;
18349
18350 $Prefix = lc($Prefix);
18351 $Prefix=~s/[_]+\Z//g;
18352
18353 foreach ("-2", "2", "-1", "1", "")
18354 { # libgnome-2.so
18355 # libxml2.so
18356 # libdbus-1.so
18357 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18358 return $Path;
18359 }
18360 }
18361 return "";
18362}
18363
18364sub getPrefix($)
18365{
18366 my $Str = $_[0];
18367 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18368 { # XmuValidArea: Xmu
18369 return $1;
18370 }
18371 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18372 { # snfReadFont: snf
18373 return $1;
18374 }
18375 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18376 { # XRRTimes: XRR
18377 return $1;
18378 }
18379 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18380 { # H5HF_delete: H5
18381 return $1;
18382 }
18383 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18384 { # alarm_event_add: alarm_
18385 return $1;
18386 }
18387 elsif($Str=~/\A(([a-z])\2{1,})/i)
18388 { # ffopen
18389 return $1;
18390 }
18391 return "";
18392}
18393
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018394sub getSymbolSize($$)
18395{ # size from the shared library
18396 my ($Symbol, $LibVersion) = @_;
18397 return 0 if(not $Symbol);
18398 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18399 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18400 {
18401 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18402 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18403 {
18404 if($Size<0) {
18405 return -$Size;
18406 }
18407 }
18408 }
18409 return 0;
18410}
18411
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018412sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018413{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18414 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018415 my ($Name, $Type) = @_;
18416
18417 # single
18418 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018419 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018420 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018421 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018422 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018423
18424 # double
18425 if($Name=~/$DEFAULT_STD_PARMS/)
18426 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018427 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018428 {
18429 my ($ShortName, $FuncParams) = split_Signature($Name);
18430
18431 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18432 {
18433 if(index($FParam, "<")!=-1)
18434 {
18435 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18436 my $FParam_N = canonifyName($FParam, "T");
18437 if($FParam_N ne $FParam) {
18438 $Name=~s/\Q$FParam\E/$FParam_N/g;
18439 }
18440 }
18441 }
18442 }
18443 elsif($Type eq "T")
18444 {
18445 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18446
18447 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018448 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018449 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018450 my $FParam = $TParams[0];
18451 foreach my $Pos (1 .. $#TParams)
18452 {
18453 my $TParam = $TParams[$Pos];
18454 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18455 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18456 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018457 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018458 }
18459 }
18460 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018461 if($Type eq "S") {
18462 return formatName($Name, "S");
18463 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018464 return $Name;
18465}
18466
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018467sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018468{
18469 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018470 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018471 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018472 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018473 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018474 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018475 next if($tr_name{$Symbol});
18476 $Symbol=~s/[\@\$]+(.*)\Z//;
18477 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018478 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018479 elsif(index($Symbol, "?")==0)
18480 {
18481 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018482 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018483 }
18484 else
18485 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018486 $tr_name{$Symbol} = $Symbol;
18487 $mangled_name_gcc{$Symbol} = $Symbol;
18488 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018489 }
18490 }
18491 if($#MnglNames1 > -1)
18492 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018493 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018494 foreach my $MnglName (@MnglNames1)
18495 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018496 if(my $Unmangled = pop(@UnmangledNames))
18497 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018498 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018499 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18500 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18501 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018502 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018503 and $tr_name{$MnglName}=~/vtable for (.+)/)
18504 { # bind class name and v-table symbol
18505 my $ClassName = $1;
18506 $ClassVTable{$ClassName} = $MnglName;
18507 $VTableClass{$MnglName} = $ClassName;
18508 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018509 }
18510 }
18511 }
18512 if($#MnglNames2 > -1)
18513 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018514 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018515 foreach my $MnglName (@MnglNames2)
18516 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018517 if(my $Unmangled = pop(@UnmangledNames))
18518 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018519 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018520 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018522 }
18523 }
18524 return \%tr_name;
18525}
18526
18527sub link_symbol($$$)
18528{
18529 my ($Symbol, $RunWith, $Deps) = @_;
18530 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18531 return 1;
18532 }
18533 if($Deps eq "+Deps")
18534 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018535 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018536 return 1;
18537 }
18538 }
18539 return 0;
18540}
18541
18542sub link_symbol_internal($$$)
18543{
18544 my ($Symbol, $RunWith, $Where) = @_;
18545 return 0 if(not $Where or not $Symbol);
18546 if($Where->{$RunWith}{$Symbol})
18547 { # the exact match by symbol name
18548 return 1;
18549 }
18550 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18551 { # indirect symbol version, i.e.
18552 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018553 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018554 if($Where->{$RunWith}{$VSym}) {
18555 return 1;
18556 }
18557 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018558 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018559 if($Sym and $Ver)
18560 { # search for the symbol with the same version
18561 # or without version
18562 if($Where->{$RunWith}{$Sym})
18563 { # old: foo@v|foo@@v
18564 # new: foo
18565 return 1;
18566 }
18567 if($Where->{$RunWith}{$Sym."\@".$Ver})
18568 { # old: foo|foo@@v
18569 # new: foo@v
18570 return 1;
18571 }
18572 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18573 { # old: foo|foo@v
18574 # new: foo@@v
18575 return 1;
18576 }
18577 }
18578 return 0;
18579}
18580
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018581sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018582{
18583 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018584 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018585 my @Imported = ();
18586 if($OSgroup eq "macos")
18587 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018588 my $NM = get_CmdPath("nm");
18589 if(not $NM) {
18590 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018591 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018592 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018593 while(<APP>)
18594 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018595 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018596 push(@Imported, $1);
18597 }
18598 }
18599 close(APP);
18600 }
18601 elsif($OSgroup eq "windows")
18602 {
18603 my $DumpBinCmd = get_CmdPath("dumpbin");
18604 if(not $DumpBinCmd) {
18605 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18606 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018607 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018608 while(<APP>)
18609 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018610 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18611 push(@Imported, $1);
18612 }
18613 }
18614 close(APP);
18615 }
18616 else
18617 {
18618 my $ReadelfCmd = get_CmdPath("readelf");
18619 if(not $ReadelfCmd) {
18620 exitStatus("Not_Found", "can't find \"readelf\"");
18621 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018622 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018623 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018624 while(<APP>)
18625 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018626 if(defined $symtab)
18627 { # do nothing with symtab
18628 if(index($_, "'.dynsym'")!=-1)
18629 { # dynamic table
18630 $symtab = undef;
18631 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018632 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018633 elsif(index($_, "'.symtab'")!=-1)
18634 { # symbol table
18635 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018636 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018637 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018638 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018639 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18640 if($Ndx eq "UND")
18641 { # only imported symbols
18642 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018643 }
18644 }
18645 }
18646 close(APP);
18647 }
18648 return @Imported;
18649}
18650
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018651my %ELF_BIND = map {$_=>1} (
18652 "WEAK",
18653 "GLOBAL"
18654);
18655
18656my %ELF_TYPE = map {$_=>1} (
18657 "FUNC",
18658 "IFUNC",
18659 "OBJECT",
18660 "COMMON"
18661);
18662
18663my %ELF_VIS = map {$_=>1} (
18664 "DEFAULT",
18665 "PROTECTED"
18666);
18667
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018668sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018669{ # read the line of 'readelf' output corresponding to the symbol
18670 my @Info = split(/\s+/, $_[0]);
18671 # Num: Value Size Type Bind Vis Ndx Name
18672 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018673 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018674 shift(@Info); # spaces
18675 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018676
18677 if($#Info==7)
18678 { # UND SYMBOL (N)
18679 if($Info[7]=~/\(\d+\)/) {
18680 pop(@Info);
18681 }
18682 }
18683
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018684 if($#Info!=6)
18685 { # other lines
18686 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018687 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018688 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018689 return () if(not defined $ELF_BIND{$Info[3]});
18690 return () if(not defined $ELF_VIS{$Info[4]});
18691 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18692 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18693 return ();
18694 }
18695 if($OStarget eq "symbian")
18696 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18697 if(index($Info[6], "_._.absent_export_")!=-1)
18698 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18699 return ();
18700 }
18701 $Info[6]=~s/\@.+//g; # remove version
18702 }
18703 if(index($Info[2], "0x") == 0)
18704 { # size == 0x3d158
18705 $Info[2] = hex($Info[2]);
18706 }
18707 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018708}
18709
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018710sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018711{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018712 my ($LibVersion, $Name) = @_;
18713 return "" if(not $LibVersion or not $Name);
18714 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18715 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018716 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018717 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18718}
18719
18720sub get_LibPath_I($$)
18721{
18722 my ($LibVersion, $Name) = @_;
18723 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018724 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018725 if(-f $Name)
18726 { # absolute path
18727 return $Name;
18728 }
18729 else
18730 { # broken
18731 return "";
18732 }
18733 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018734 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018735 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018736 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018737 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018738 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018739 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018740 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018741 }
18742 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18743 { # ldconfig default paths
18744 return $DefaultPath;
18745 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018746 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018747 { # search in default linker directories
18748 # and then in all system paths
18749 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018750 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018751 }
18752 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018753 if(not defined $Cache{"checkSystemFiles"}) {
18754 checkSystemFiles();
18755 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018756 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18757 return $AllObjects[0];
18758 }
18759 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18760 {
18761 if($ShortName ne $Name)
18762 { # FIXME: check this case
18763 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18764 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018765 }
18766 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018767 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018768 # can't find
18769 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018770}
18771
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018772sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018773{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018774 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18775 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018776
18777 my $Real_Path = realpath($Lib_Path);
18778
18779 if(not $Real_Path)
18780 { # broken link
18781 return ();
18782 }
18783
18784 my $Lib_Name = get_filename($Real_Path);
18785
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018786 if($ExtraInfo)
18787 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018788 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018789 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018790 }
18791
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018792 if($IsNeededLib)
18793 {
18794 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18795 return ();
18796 }
18797 }
18798 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018799 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018800
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018801 push(@RecurLib, $Lib_Name);
18802 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018803 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18804
18805 if(not $IsNeededLib)
18806 { # special cases: libstdc++ and libc
18807 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18808 {
18809 if($ShortName eq "libstdc++")
18810 { # libstdc++.so.6
18811 $STDCXX_TESTING = 1;
18812 }
18813 elsif($ShortName eq "libc")
18814 { # libc-2.11.3.so
18815 $GLIBC_TESTING = 1;
18816 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018817 }
18818 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018819 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018820 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018821 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018822 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018823 mkpath(get_dirname($DebugPath));
18824 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018825 if($OStarget eq "macos")
18826 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018827 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018828 if(not $NM) {
18829 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018830 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018831 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018832 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018833 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018834 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018835 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018836 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018837 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018838 else
18839 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018840 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018842 while(<LIB>)
18843 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018844 if($CheckUndefined)
18845 {
18846 if(not $IsNeededLib)
18847 {
18848 if(/ U _([\w\$]+)\s*\Z/)
18849 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018850 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018851 next;
18852 }
18853 }
18854 }
18855
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018856 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018857 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018858 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018859 if($IsNeededLib)
18860 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018861 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018862 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018863 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18864 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018865 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018866 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018867 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018868 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018869 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18870 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018871 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18872 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018873 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018874 setLanguage($LibVersion, "C++");
18875 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018876 }
18877 if($CheckObjectsOnly
18878 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018879 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018880 }
18881 }
18882 }
18883 }
18884 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018885
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018886 if($Deps)
18887 {
18888 if($LIB_TYPE eq "dynamic")
18889 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018890
18891 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018892 if(not $OtoolCmd) {
18893 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018894 }
18895
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018896 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18897 while(<LIB>)
18898 {
18899 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18900 and $1 ne $Lib_Path) {
18901 $NeededLib{$1} = 1;
18902 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018903 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018904 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018906 }
18907 }
18908 elsif($OStarget eq "windows")
18909 { # Windows *.dll, *.lib
18910 my $DumpBinCmd = get_CmdPath("dumpbin");
18911 if(not $DumpBinCmd) {
18912 exitStatus("Not_Found", "can't find \"dumpbin\"");
18913 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018914 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018915 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018916 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018917 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018918 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018919 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018920 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018921 else
18922 { # write to pipe
18923 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018924 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018925 while(<LIB>)
18926 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18927 # 1198 4AD SetThreadToken (forwarded to ...)
18928 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018929 # 1 0 00005B30 ??0?N = ... (with pdb)
18930 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018931 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018932 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018933 { # dynamic, static and forwarded symbols
18934 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018935 if($IsNeededLib)
18936 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018937 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018938 {
18939 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18940 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18941 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018942 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018943 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018944 {
18945 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18946 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018947 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18948 {
18949 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18950 setLanguage($LibVersion, "C++");
18951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018952 }
18953 if($CheckObjectsOnly
18954 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018955 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018956 }
18957 }
18958 }
18959 }
18960 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018961
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018962 if($Deps)
18963 {
18964 if($LIB_TYPE eq "dynamic")
18965 { # dependencies
18966 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18967 while(<LIB>)
18968 {
18969 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
18970 and $1 ne $Lib_Path) {
18971 $NeededLib{path_format($1, $OSgroup)} = 1;
18972 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018973 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018974 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018976 }
18977 }
18978 else
18979 { # Unix; *.so, *.a
18980 # Symbian: *.dso, *.lib
18981 my $ReadelfCmd = get_CmdPath("readelf");
18982 if(not $ReadelfCmd) {
18983 exitStatus("Not_Found", "can't find \"readelf\"");
18984 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018985 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018986 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018987 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018988 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018989 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018990 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018991 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018992 else
18993 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018994 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018995 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018996 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018997 while(<LIB>)
18998 {
18999 if($LIB_TYPE eq "dynamic")
19000 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019001 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019002 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019003 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019004 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019005 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019006 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019007 # do nothing with symtab
19008 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019009 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019010 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019011 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019012 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019013 next;
19014 }
19015 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019016 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019017 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019018 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019019 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019020 if($CheckUndefined)
19021 {
19022 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019023 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019024 }
19025 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019026 next;
19027 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019028 if($Bind eq "WEAK")
19029 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019030 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019031 if($Weak eq "-Weak")
19032 { # skip WEAK symbols
19033 next;
19034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019035 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019036 my $Short = $Symbol;
19037 $Short=~s/\@.+//g;
19038 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019039 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019040 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19041 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019042 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019043 if($IsNeededLib)
19044 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019045 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019046 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019047 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19048 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019050 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019051 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019052 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019053 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19054 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19055 if($Vers)
19056 {
19057 if($LIB_EXT eq "so")
19058 { # value
19059 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19060 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19061 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019062 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019063 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19064 {
19065 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19066 setLanguage($LibVersion, "C++");
19067 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019068 }
19069 if($CheckObjectsOnly
19070 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019071 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019072 }
19073 }
19074 }
19075 }
19076 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019077
19078 if($Deps and $LIB_TYPE eq "dynamic")
19079 { # dynamic library specifics
19080 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19081 open(LIB, $Cmd." |");
19082
19083 while(<LIB>)
19084 {
19085 if(/NEEDED.+\[([^\[\]]+)\]/)
19086 { # dependencies:
19087 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19088 $NeededLib{$1} = 1;
19089 }
19090 }
19091
19092 close(LIB);
19093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019094 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019095 if($Vers)
19096 {
19097 if(not $IsNeededLib and $LIB_EXT eq "so")
19098 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019099 my %Found = ();
19100
19101 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019102 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019103 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019104 next if(index($Symbol,"\@")==-1);
19105 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019106 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019107 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019108 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019109 if($Symbol_SameValue ne $Symbol
19110 and index($Symbol_SameValue,"\@")==-1)
19111 {
19112 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019113 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019114 last;
19115 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019116 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019117 }
19118 }
19119
19120 # default
19121 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19122 {
19123 next if(defined $Found{$Symbol});
19124 next if(index($Symbol,"\@\@")==-1);
19125
19126 if($Symbol=~/\A([^\@]*)\@\@/
19127 and not $SymVer{$LibVersion}{$1})
19128 {
19129 $SymVer{$LibVersion}{$1} = $Symbol;
19130 $Found{$Symbol} = 1;
19131 }
19132 }
19133
19134 # non-default
19135 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19136 {
19137 next if(defined $Found{$Symbol});
19138 next if(index($Symbol,"\@")==-1);
19139
19140 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19141 and not $SymVer{$LibVersion}{$1})
19142 {
19143 $SymVer{$LibVersion}{$1} = $Symbol;
19144 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019145 }
19146 }
19147 }
19148 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019149 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019150 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019151 foreach my $DyLib (sort keys(%NeededLib))
19152 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019153 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19154
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019155 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19156 {
19157 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19158 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19159 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019160 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019161 }
19162 }
19163 pop(@RecurLib);
19164 return $Library_Symbol{$LibVersion};
19165}
19166
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019167sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019168{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019169 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019170 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019171 return keys(%Prefixes);
19172}
19173
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019174sub get_prefixes_I($$)
19175{
19176 foreach my $P (@{$_[0]})
19177 {
19178 my @Parts = reverse(split(/[\/\\]+/, $P));
19179 my $Name = $Parts[0];
19180 foreach (1 .. $#Parts)
19181 {
19182 $_[1]->{$Name}{$P} = 1;
19183 last if($_>4 or $Parts[$_] eq "include");
19184 $Name = $Parts[$_].$SLASH.$Name;
19185 }
19186 }
19187}
19188
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019189sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019190{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019191 $Cache{"checkSystemFiles"} = 1;
19192
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019193 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019194
19195 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019196 {
19197 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019198
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019199 my @Files = cmd_find($DevelPath,"f");
19200 foreach my $Link (cmd_find($DevelPath,"l"))
19201 { # add symbolic links
19202 if(-f $Link) {
19203 push(@Files, $Link);
19204 }
19205 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019206
19207 if(not $CheckObjectsOnly)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019208 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019209 # search for headers in /usr/lib
Andrey Ponomarenko13bb0332013-06-28 15:32:28 +040019210 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19211 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19212 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019213 }
19214
19215 # search for libraries in /usr/lib (including symbolic links)
19216 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19217 foreach my $Path (@Libs)
19218 {
19219 my $N = get_filename($Path);
19220 $SystemObjects{$N}{$Path} = 1;
19221 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019222 }
19223 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019224
19225 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019226 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019227 foreach my $DevelPath (@{$SystemPaths{"include"}})
19228 {
19229 next if(not -d $DevelPath);
19230 # search for all header files in the /usr/include
19231 # with or without extension (ncurses.h, QtCore, ...)
19232 push(@SysHeaders, cmd_find($DevelPath,"f"));
19233 foreach my $Link (cmd_find($DevelPath,"l"))
19234 { # add symbolic links
19235 if(-f $Link) {
19236 push(@SysHeaders, $Link);
19237 }
19238 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019239 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019240 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019241 }
19242}
19243
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019244sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019245{
19246 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019247 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019248 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19249 {
19250 if(not -e $Dest) {
19251 exitStatus("Access_Error", "can't access \'$Dest\'");
19252 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019253 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019254 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19255 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019256 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019257 }
19258 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019259 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019260}
19261
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019262sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019263{
19264 my ($Path, $LibVersion) = @_;
19265 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019266 my $Name = get_filename($Path);
19267 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019268 return 1;
19269 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019270 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019271 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19272 return 1;
19273 }
19274 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19275 {
19276 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19277 return 1;
19278 }
19279 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019280 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019281 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019282 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019283 return 1;
19284 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019285 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019286 return 1;
19287 }
19288 }
19289 return 0;
19290}
19291
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019292sub specificHeader($$)
19293{
19294 my ($Header, $Spec) = @_;
19295 my $Name = get_filename($Header);
19296
19297 if($Spec eq "windows")
19298 {# MS Windows
19299 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19300 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19301 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19302 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19303 my @Dirs = (
19304 "win32",
19305 "win64",
19306 "win",
19307 "windows",
19308 "msvcrt"
19309 ); # /gsf-win32/
19310 if(my $DIRs = join("|", @Dirs)) {
19311 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19312 }
19313 }
19314 elsif($Spec eq "macos")
19315 { # Mac OS
19316 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19317 }
19318
19319 return 0;
19320}
19321
19322sub skipAlienHeader($)
19323{
19324 my $Path = $_[0];
19325 my $Name = get_filename($Path);
19326 my $Dir = get_dirname($Path);
19327
19328 if($Tolerance=~/2/)
19329 { # 2 - skip internal headers
19330 my @Terms = (
19331 "p",
19332 "priv",
19333 "int",
19334 "impl",
19335 "implementation",
19336 "internal",
19337 "private",
19338 "old",
19339 "compat",
19340 "debug",
19341 "test",
19342 "gen"
19343 );
19344
19345 my @Dirs = (
19346 "private",
19347 "priv",
19348 "port",
19349 "impl",
19350 "internal",
19351 "detail",
19352 "details",
19353 "old",
19354 "compat",
19355 "debug",
19356 "config",
19357 "compiler",
19358 "platform",
19359 "test"
19360 );
19361
19362 if(my $TERMs = join("|", @Terms)) {
19363 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19364 }
19365 if(my $DIRs = join("|", @Dirs)) {
19366 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19367 }
19368
19369 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19370 }
19371
19372 if($Tolerance=~/1/)
19373 { # 1 - skip non-Linux headers
19374 if($OSgroup ne "windows")
19375 {
19376 if(specificHeader($Path, "windows")) {
19377 return 1;
19378 }
19379 }
19380 if($OSgroup ne "macos")
19381 {
19382 if(specificHeader($Path, "macos")) {
19383 return 1;
19384 }
19385 }
19386 }
19387
19388 # valid
19389 return 0;
19390}
19391
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019392sub skipHeader($$)
19393{
19394 my ($Path, $LibVersion) = @_;
19395 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019396 if(defined $Cache{"skipHeader"}{$Path}) {
19397 return $Cache{"skipHeader"}{$Path};
19398 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019399 if(defined $Tolerance and $Tolerance=~/1|2/)
19400 { # --tolerant
19401 if(skipAlienHeader($Path)) {
19402 return ($Cache{"skipHeader"}{$Path} = 1);
19403 }
19404 }
19405 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19406 return 0;
19407 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019408 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19409}
19410
19411sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019412{ # returns:
19413 # 1 - if header should NOT be included and checked
19414 # 2 - if header should NOT be included, but should be checked
19415 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019416 my $Name = get_filename($Path);
19417 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019418 return $Kind;
19419 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019420 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19421 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019422 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019423 if(index($Path, $D)!=-1)
19424 {
19425 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19426 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19427 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019428 }
19429 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019430 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19431 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019432 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019433 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19434 {
19435 if($Name=~/$P/) {
19436 return $Kind;
19437 }
19438 if($P=~/[\/\\]/ and $Path=~/$P/) {
19439 return $Kind;
19440 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019441 }
19442 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019443
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019444 return 0;
19445}
19446
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019447sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019448{
19449 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019450 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019451 { # system directory
19452 return;
19453 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019454 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019455 { # already registered
19456 return;
19457 }
19458 foreach my $Path (find_libs($Dir,"",1))
19459 {
19460 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019461 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019462 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019463 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019464 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19465}
19466
19467sub registerObject($$)
19468{
19469 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019470
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019471 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019472 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019473 if($OSgroup=~/linux|bsd/i)
19474 {
19475 if(my $SONAME = getSONAME($Path)) {
19476 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19477 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019478 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019479 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19480 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019481 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019482
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019483 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019484 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019485 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019486 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019487 if($ObjArch ne getArch_GCC($LibVersion))
19488 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19489 $CheckedArch{$LibVersion} = 1;
19490 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 +040019491 }
19492 }
19493 }
19494}
19495
19496sub getArch_Object($)
19497{
19498 my $Path = $_[0];
19499
19500 my %MachineType = (
19501 "14C" => "x86",
19502 "8664" => "x86_64",
19503 "1C0" => "arm",
19504 "200" => "ia64"
19505 );
19506
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019507 my %ArchName = (
19508 "s390:31-bit" => "s390",
19509 "s390:64-bit" => "s390x",
19510 "powerpc:common" => "ppc32",
19511 "powerpc:common64" => "ppc64",
19512 "i386:x86-64" => "x86_64",
19513 "mips:3000" => "mips",
19514 "sparc:v8plus" => "sparcv9"
19515 );
19516
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019517 if($OSgroup eq "windows")
19518 {
19519 my $DumpbinCmd = get_CmdPath("dumpbin");
19520 if(not $DumpbinCmd) {
19521 exitStatus("Not_Found", "can't find \"dumpbin\"");
19522 }
19523
19524 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19525 my $Out = `$Cmd`;
19526
19527 if($Out=~/(\w+)\smachine/)
19528 {
19529 if(my $Type = $MachineType{uc($1)})
19530 {
19531 return $Type;
19532 }
19533 }
19534 }
19535 elsif($OSgroup=~/linux|bsd/)
19536 {
19537 my $ObjdumpCmd = get_CmdPath("objdump");
19538 if(not $ObjdumpCmd) {
19539 exitStatus("Not_Found", "can't find \"objdump\"");
19540 }
19541
19542 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030019543 my $Out = `$LOCALE $Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019544
19545 if($Out=~/architecture:\s+([\w\-\:]+)/)
19546 {
19547 my $Arch = $1;
19548 if($Arch=~s/\:(.+)//)
19549 {
19550 my $Suffix = $1;
19551
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019552 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019553 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019554 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019555 }
19556 }
19557
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019558 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019559 $Arch = "x86";
19560 }
19561
19562 if($Arch eq "x86-64") {
19563 $Arch = "x86_64";
19564 }
19565
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019566 if($Arch eq "ia64-elf64") {
19567 $Arch = "ia64";
19568 }
19569
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019570 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019571 }
19572 }
19573 else
19574 { # macos, etc.
19575 # TODO
19576 }
19577
19578 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019579}
19580
19581sub getSONAME($)
19582{
19583 my $Path = $_[0];
19584 return if(not $Path);
19585 if(defined $Cache{"getSONAME"}{$Path}) {
19586 return $Cache{"getSONAME"}{$Path};
19587 }
19588 my $ObjdumpCmd = get_CmdPath("objdump");
19589 if(not $ObjdumpCmd) {
19590 exitStatus("Not_Found", "can't find \"objdump\"");
19591 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019592 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019593 if($OSgroup eq "windows") {
19594 $SonameCmd .= " | find \"SONAME\"";
19595 }
19596 else {
19597 $SonameCmd .= " | grep SONAME";
19598 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019599 if(my $SonameInfo = `$SonameCmd`)
19600 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019601 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19602 return ($Cache{"getSONAME"}{$Path} = $1);
19603 }
19604 }
19605 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019606}
19607
19608sub getSOPaths_Dest($$)
19609{
19610 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019611 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019612 return ();
19613 }
19614 if(-f $Dest)
19615 {
19616 if(not parse_libname($Dest, "name", $OStarget)) {
19617 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19618 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019619 registerObject($Dest, $LibVersion);
19620 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019621 return ($Dest);
19622 }
19623 elsif(-d $Dest)
19624 {
19625 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019626 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019627 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019628 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19629 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019630 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019631 { # all files and symlinks that match the name of a library
19632 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19633 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019634 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019635 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019636 }
19637 }
19638 }
19639 else
19640 { # search for all files and symlinks
19641 foreach my $Path (find_libs($Dest,"",""))
19642 {
19643 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019644 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019645 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019646 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019647 }
19648 if($OSgroup eq "macos")
19649 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019650 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019651 {
19652 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019653 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019654 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019655 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19656 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019657 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019658 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019659 }
19660 }
19661 }
19662 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019663 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019664 }
19665 else {
19666 return ();
19667 }
19668}
19669
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019670sub isCyclical($$)
19671{
19672 my ($Stack, $Value) = @_;
19673 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019674}
19675
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019676sub getGCC_Opts($)
19677{ # to use in module
19678 my $LibVersion = $_[0];
19679
19680 my @Opts = ();
19681
19682 if($CompilerOptions{$LibVersion})
19683 { # user-defined options
19684 push(@Opts, $CompilerOptions{$LibVersion});
19685 }
19686 if($GccOptions)
19687 { # additional
19688 push(@Opts, $GccOptions);
19689 }
19690
19691 if(@Opts) {
19692 return join(" ", @Opts);
19693 }
19694
19695 return undef;
19696}
19697
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019698sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019699{
19700 my $LibVersion = $_[0];
19701
19702 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19703 return $Cache{"getArch_GCC"}{$LibVersion};
19704 }
19705
19706 my $Arch = undef;
19707
19708 if($GCC_PATH)
19709 {
19710 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19711
19712 my $Cmd = $GCC_PATH." test.c -o test";
19713 if(my $Opts = getGCC_Opts($LibVersion))
19714 { # user-defined options
19715 $Cmd .= " ".$Opts;
19716 }
19717
19718 chdir($TMP_DIR);
19719 system($Cmd);
19720 chdir($ORIG_DIR);
19721
19722 $Arch = getArch_Object("$TMP_DIR/test");
19723
19724 unlink("$TMP_DIR/test.c");
19725 unlink("$TMP_DIR/test");
19726 }
19727
19728 if(not $Arch) {
19729 exitStatus("Error", "can't check ARCH type");
19730 }
19731
19732 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19733}
19734
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019735sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019736{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019737 my $LibVersion = $_[0];
19738
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019739 my $Size = undef;
19740
19741 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019742 if(my $Arch = getArch($LibVersion))
19743 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019744 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019745 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019746 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019747 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19748 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019749 }
19750 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019751
19752 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019753 {
19754 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019755
19756 my $Cmd = $GCC_PATH." -E -dD empty.h";
19757 if(my $Opts = getGCC_Opts($LibVersion))
19758 { # user-defined options
19759 $Cmd .= " ".$Opts;
19760 }
19761
19762 chdir($TMP_DIR);
19763 my $Defines = `$Cmd`;
19764 chdir($ORIG_DIR);
19765
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019766 unlink("$TMP_DIR/empty.h");
19767
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019768 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19769 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019770 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019771 }
19772 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19773 { # GCC 3
19774 my $PTRDIFF = $1;
19775 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019776 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019777 }
19778 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019779 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019780 }
19781 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019782 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019783
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019784 if(not $Size) {
19785 exitStatus("Error", "can't check WORD size");
19786 }
19787
19788 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019789}
19790
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019791sub getWordSize($)
19792{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019793 return $WORD_SIZE{$_[0]};
19794}
19795
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019796sub majorVersion($)
19797{
19798 my $V = $_[0];
19799 return 0 if(not $V);
19800 my @VParts = split(/\./, $V);
19801 return $VParts[0];
19802}
19803
19804sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019805{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019806 my ($V1, $V2) = @_;
19807 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019808 my @V1Parts = split(/\./, $V1);
19809 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019810 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19811 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019812 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19813 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19814 }
19815 return -1 if($#V1Parts < $#V2Parts);
19816 return 1 if($#V1Parts > $#V2Parts);
19817 return 0;
19818}
19819
19820sub read_ABI_Dump($$)
19821{
19822 my ($LibVersion, $Path) = @_;
19823 return if(not $LibVersion or not -e $Path);
19824 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019825 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019826 { # input *.abi
19827 $FilePath = $Path;
19828 }
19829 else
19830 { # input *.abi.tar.gz
19831 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019832 if(not isDump_U($FilePath)) {
19833 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19834 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019835 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019836
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019837 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019838
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019839 my $Line = readLineNum($FilePath, 0);
19840 if($Line=~/xml/)
19841 { # XML format
19842 loadModule("XmlDump");
19843 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019844 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019845 else
19846 { # Perl Data::Dumper format (default)
19847 open(DUMP, $FilePath);
19848 local $/ = undef;
19849 my $Content = <DUMP>;
19850 close(DUMP);
19851
19852 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19853 { # remove temp file
19854 unlink($FilePath);
19855 }
19856 if($Content!~/};\s*\Z/) {
19857 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19858 }
19859 $ABI = eval($Content);
19860 if(not $ABI) {
19861 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019863 }
19864 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019865 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019866 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019867 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019868 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019869 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019870 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019871 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030019872 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019873
19874 if($ABI->{"ABI_DUMP_VERSION"})
19875 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019876 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019877 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019878 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019879 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019880 }
19881 else
19882 { # support for old ABI dumps
19883 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019884 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019885 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019886 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019887 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019888
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019889 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019890 {
19891 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 +040019892 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019893
19894 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19895 { # DWARF ABI Dump
19896 $UseConv_Real{$LibVersion}{"P"} = 1;
19897 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19898
19899 $UsedDump{$LibVersion}{"DWARF"} = 1;
19900
19901 $TargetComponent = "module";
19902 }
19903
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019904 if(not checkDump($LibVersion, "2.11"))
19905 { # old ABI dumps
19906 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019907 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019908 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019909 { # ABI dump created with --binary option
19910 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19911 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019912 else
19913 { # default
19914 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19915 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019916
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019917 if(defined $ABI->{"Mode"}
19918 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019919 { # --ext option
19920 $ExtendedCheck = 1;
19921 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019922 if($ABI->{"Extra"}) {
19923 $ExtraDump = 1;
19924 }
19925
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019926 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019927 {
19928 $UsedDump{$LibVersion}{"L"} = $Lang;
19929 setLanguage($LibVersion, $Lang);
19930 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019931 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019932 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019933 }
19934 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019935 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019936 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019937 if(not $TInfo)
19938 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019939 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019940 }
19941 my %Tid_TDid = ();
19942 foreach my $TDid (keys(%{$TInfo}))
19943 {
19944 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19945 {
19946 $MAX_ID = $Tid if($Tid>$MAX_ID);
19947 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019948 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019949 }
19950 }
19951 my %NewID = ();
19952 foreach my $Tid (keys(%Tid_TDid))
19953 {
19954 my @TDids = keys(%{$Tid_TDid{$Tid}});
19955 if($#TDids>=1)
19956 {
19957 foreach my $TDid (@TDids)
19958 {
19959 if($TDid) {
19960 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19961 }
19962 else
19963 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019964 my $ID = ++$MAX_ID;
19965
19966 $NewID{$TDid}{$Tid} = $ID;
19967 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19968 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019969 }
19970 }
19971 }
19972 else
19973 {
19974 my $TDid = $TDids[0];
19975 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19976 }
19977 }
19978 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
19979 {
19980 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
19981 if(defined $Info{"BaseType"})
19982 {
19983 my $Bid = $Info{"BaseType"}{"Tid"};
19984 my $BDid = $Info{"BaseType"}{"TDid"};
19985 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019986 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019987 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
19988 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
19989 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019990 }
19991 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
19992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019993 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019994 read_Machine_DumpInfo($ABI, $LibVersion);
19995 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019996 if(not $SymbolInfo{$LibVersion})
19997 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019998 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019999 }
20000 if(not keys(%{$SymbolInfo{$LibVersion}}))
20001 { # validation of old-version dumps
20002 if(not $ExtendedCheck) {
20003 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20004 }
20005 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020006 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020007 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020008 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020009 else
20010 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020011 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020012 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020013 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020014 }
20015 if(not $DepSymbols)
20016 { # Cannot reconstruct DepSymbols. This may result in false
20017 # positives if the old dump is for library 2. Not a problem if
20018 # old dumps are only from old libraries.
20019 $DepSymbols = {};
20020 }
20021 foreach my $Symbol (keys(%{$DepSymbols})) {
20022 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020024 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020025 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020026
20027 if(my $V = $TargetVersion{$LibVersion}) {
20028 $Descriptor{$LibVersion}{"Version"} = $V;
20029 }
20030 else {
20031 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20032 }
20033
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020034 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020035 if(not $SkipTypes{$LibVersion})
20036 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020037 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020038 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020039
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020040 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020041 { # if not defined by -skip-symbols option
20042 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20043 if(not $SkipSymbols{$LibVersion})
20044 { # support for old dumps
20045 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20046 }
20047 if(not $SkipSymbols{$LibVersion})
20048 { # support for old dumps
20049 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20050 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020051 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020052 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020053
20054 if(not $TargetHeaders{$LibVersion})
20055 { # if not defined by -headers-list option
20056 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20057 }
20058
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020059 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020060 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020061 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020062 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020063 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020064 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020065 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020066 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020067 if(not checkDump($LibVersion, "2.10.1")
20068 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020069 { # support for old ABI dumps: added target headers
20070 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020071 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020072 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020073 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020074 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020075 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020076 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020077 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020078 if(defined $ABI->{"GccConstants"})
20079 { # 3.0
20080 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20081 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20082 }
20083 }
20084
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020085 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020086 if(not $NestedNameSpaces{$LibVersion})
20087 { # support for old dumps
20088 # Cannot reconstruct NameSpaces. This may affect design
20089 # of the compatibility report.
20090 $NestedNameSpaces{$LibVersion} = {};
20091 }
20092 # target system type
20093 # needed to adopt HTML report
20094 if(not $DumpSystem)
20095 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020096 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020097 }
20098 # recreate environment
20099 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20100 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020101 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020102 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020103 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20104 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020105 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020106 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020107 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020108 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20109 {
20110 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20111 setLanguage($LibVersion, "C++");
20112 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020113 }
20114 }
20115 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020116 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20117 {
20118 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20119 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20120 }
20121 }
20122
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020123 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020124 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020125 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020126 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020127 {
20128 if(not $Symbol_Library{$LibVersion}{$MnglName}
20129 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20130 push(@VFunc, $MnglName);
20131 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020132 }
20133 }
20134 translateSymbols(@VFunc, $LibVersion);
20135 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020136 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20137
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020138 if(not checkDump($LibVersion, "3.0"))
20139 { # support for old ABI dumps
20140 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20141 {
20142 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20143 {
20144 if(ref($BaseType) eq "HASH") {
20145 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20146 }
20147 }
20148 }
20149 }
20150
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020151 if(not checkDump($LibVersion, "3.2"))
20152 { # support for old ABI dumps
20153 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20154 {
20155 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20156 {
20157 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20158 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20159 }
20160 }
20161 }
20162
20163 # repair target headers list
20164 delete($TargetHeaders{$LibVersion});
20165 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020166 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20167 }
20168 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20169 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020170 }
20171
20172 # non-target constants from anon enums
20173 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20174 {
20175 if(not $ExtraDump
20176 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20177 {
20178 delete($Constants{$LibVersion}{$Name});
20179 }
20180 }
20181 }
20182
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020183 if(not checkDump($LibVersion, "2.20"))
20184 { # support for old ABI dumps
20185 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20186 {
20187 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20188
20189 if($TType=~/Struct|Union|Enum|Typedef/)
20190 { # repair complex types first
20191 next;
20192 }
20193
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020194 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020195 {
20196 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20197 if($BType=~/Struct|Union|Enum/i)
20198 {
20199 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20200 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20201 }
20202 }
20203 }
20204 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20205 {
20206 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20207 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20208 if($TType=~/Struct|Union|Enum/) {
20209 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20210 }
20211 }
20212 }
20213
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020214 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020215 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020216 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20217 { # support for old ABI dumps < 2.0 (ACC 1.22)
20218 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20219 {
20220 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20221 {
20222 if($Access ne "public") {
20223 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20224 }
20225 }
20226 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20227 }
20228 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20229 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020230 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20231 { # support for old ABI dumps
20232 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20233 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020234 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20235 { # DWARF ABI Dumps
20236 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20237 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020238 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20239 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20240 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020241 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20242 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020243 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020244 foreach (keys(%{$TInfo{"Base"}})) {
20245 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020246 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020247 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020248 if($TInfo{"Type"} eq "MethodPtr")
20249 {
20250 if(defined $TInfo{"Param"})
20251 { # support for old ABI dumps <= 1.17
20252 if(not defined $TInfo{"Param"}{"0"})
20253 {
20254 my $Max = keys(%{$TInfo{"Param"}});
20255 foreach my $Pos (1 .. $Max) {
20256 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20257 }
20258 delete($TInfo{"Param"}{$Max});
20259 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20260 }
20261 }
20262 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020263 if($TInfo{"BaseType"} eq $TypeId)
20264 { # fix ABI dump
20265 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20266 }
20267 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020268 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020269 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020270 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020271 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20272 if(not $BName)
20273 { # broken type
20274 next;
20275 }
20276 if($TInfo{"Name"} eq $BName)
20277 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020278 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020279 next;
20280 }
20281 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20282 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020283 }
20284 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020285 }
20286 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20287 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020288 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020289 }
20290 }
20291
20292 if(not checkDump($LibVersion, "2.15"))
20293 { # support for old ABI dumps
20294 my %Dups = ();
20295 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20296 {
20297 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020298 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020299 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20300 { # remove template decls
20301 delete($SymbolInfo{$LibVersion}{$InfoId});
20302 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020303 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020304 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020305 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20306 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020307 { # templates
20308 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020309 }
20310 }
20311 }
20312
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020313 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20314 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020315 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20316 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20317 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20318 { # support for old ABI dumps (< 3.1)
20319 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20320 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20321 { # add "this" first parameter
20322 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20323 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20324
20325 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20326 {
20327 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20328 foreach my $Pos (reverse(0 .. $#Pos)) {
20329 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20330 }
20331 }
20332 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20333 }
20334 }
20335
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020336 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20337 { # ABI dumps have no mangled names for C-functions
20338 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20339 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020340 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20341 { # support for old ABI dumps
20342 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20343 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020344 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20345 { # DWARF ABI Dumps
20346 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20347 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020348 }
20349
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020350 $Descriptor{$LibVersion}{"Dump"} = 1;
20351}
20352
20353sub read_Machine_DumpInfo($$)
20354{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020355 my ($ABI, $LibVersion) = @_;
20356 if($ABI->{"Arch"}) {
20357 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020358 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020359 if($ABI->{"WordSize"}) {
20360 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020361 }
20362 else
20363 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020364 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020365 }
20366 if(not $WORD_SIZE{$LibVersion})
20367 { # support for old dumps (<1.23)
20368 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20369 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020370 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020371 }
20372 else
20373 {
20374 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020375 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020376 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020377 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20378 { # any "pointer"-type
20379 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020380 last;
20381 }
20382 }
20383 if($PSize)
20384 { # a pointer type size
20385 $WORD_SIZE{$LibVersion} = $PSize;
20386 }
20387 else {
20388 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20389 }
20390 }
20391 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020392 if($ABI->{"GccVersion"}) {
20393 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020394 }
20395}
20396
20397sub read_Libs_DumpInfo($$)
20398{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020399 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020400 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20401 if(not $Library_Symbol{$LibVersion})
20402 { # support for old dumps
20403 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20404 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020405 if(keys(%{$Library_Symbol{$LibVersion}})
20406 and not $DumpAPI) {
20407 $Descriptor{$LibVersion}{"Libs"} = "OK";
20408 }
20409}
20410
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020411sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020412{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020413 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020414
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020415 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020416 and not $DumpAPI) {
20417 $Descriptor{$LibVersion}{"Headers"} = "OK";
20418 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020419 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020420 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020421 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020422 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020423 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020424
20425 if(keys(%{$ABI->{"Sources"}})
20426 and not $DumpAPI) {
20427 $Descriptor{$LibVersion}{"Sources"} = "OK";
20428 }
20429 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020430 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020431 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20432 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20433 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020434}
20435
20436sub find_libs($$$)
20437{
20438 my ($Path, $Type, $MaxDepth) = @_;
20439 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020440 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020441}
20442
20443sub createDescriptor($$)
20444{
20445 my ($LibVersion, $Path) = @_;
20446 if(not $LibVersion or not $Path
20447 or not -e $Path) {
20448 return "";
20449 }
20450 if(-d $Path)
20451 { # directory with headers files and shared objects
20452 return "
20453 <version>
20454 ".$TargetVersion{$LibVersion}."
20455 </version>
20456
20457 <headers>
20458 $Path
20459 </headers>
20460
20461 <libs>
20462 $Path
20463 </libs>";
20464 }
20465 else
20466 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020467 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020468 { # standard XML-descriptor
20469 return readFile($Path);
20470 }
20471 elsif(is_header($Path, 2, $LibVersion))
20472 { # header file
20473 return "
20474 <version>
20475 ".$TargetVersion{$LibVersion}."
20476 </version>
20477
20478 <headers>
20479 $Path
20480 </headers>
20481
20482 <libs>
20483 none
20484 </libs>";
20485 }
20486 elsif(parse_libname($Path, "name", $OStarget))
20487 { # shared object
20488 return "
20489 <version>
20490 ".$TargetVersion{$LibVersion}."
20491 </version>
20492
20493 <headers>
20494 none
20495 </headers>
20496
20497 <libs>
20498 $Path
20499 </libs>";
20500 }
20501 else
20502 { # standard XML-descriptor
20503 return readFile($Path);
20504 }
20505 }
20506}
20507
20508sub detect_lib_default_paths()
20509{
20510 my %LPaths = ();
20511 if($OSgroup eq "bsd")
20512 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020513 if(my $LdConfig = get_CmdPath("ldconfig"))
20514 {
20515 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20516 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020517 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20518 {
20519 my $Name = "lib".$1;
20520 if(not defined $LPaths{$Name}) {
20521 $LPaths{$Name} = $2;
20522 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020523 }
20524 }
20525 }
20526 else {
20527 printMsg("WARNING", "can't find ldconfig");
20528 }
20529 }
20530 else
20531 {
20532 if(my $LdConfig = get_CmdPath("ldconfig"))
20533 {
20534 if($SystemRoot and $OSgroup eq "linux")
20535 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20536 if(-e $SystemRoot."/etc/ld.so.conf") {
20537 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20538 }
20539 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020540 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20541 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020542 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20543 {
20544 my ($Name, $Path) = ($1, $2);
20545 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020546 if(not defined $LPaths{$Name})
20547 { # get first element from the list of available paths
20548
20549 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20550 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20551 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20552
20553 $LPaths{$Name} = $Path;
20554 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020555 }
20556 }
20557 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020558 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020559 printMsg("WARNING", "can't find ldconfig");
20560 }
20561 }
20562 return \%LPaths;
20563}
20564
20565sub detect_bin_default_paths()
20566{
20567 my $EnvPaths = $ENV{"PATH"};
20568 if($OSgroup eq "beos") {
20569 $EnvPaths.=":".$ENV{"BETOOLS"};
20570 }
20571 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020572 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020573 {
20574 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020575 next if(not $Path);
20576 if($SystemRoot
20577 and $Path=~/\A\Q$SystemRoot\E\//)
20578 { # do NOT use binaries from target system
20579 next;
20580 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020581 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020582 }
20583}
20584
20585sub detect_inc_default_paths()
20586{
20587 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020588 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020589 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020590 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020591 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020592 next if(index($Line, "/cc1plus ")!=-1);
20593
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020594 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20595 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020596 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020597 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020598 if(index($Path, "c++")!=-1
20599 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020600 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020601 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020602 if(not defined $MAIN_CPP_DIR
20603 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20604 $MAIN_CPP_DIR = $Path;
20605 }
20606 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020607 elsif(index($Path, "gcc")!=-1) {
20608 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020609 }
20610 else
20611 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020612 if($Path=~/local[\/\\]+include/)
20613 { # local paths
20614 next;
20615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020616 if($SystemRoot
20617 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20618 { # The GCC include path for user headers is not a part of the system root
20619 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20620 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20621 next;
20622 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020623 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020624 }
20625 }
20626 }
20627 unlink("$TMP_DIR/empty.h");
20628 return %DPaths;
20629}
20630
20631sub detect_default_paths($)
20632{
20633 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20634 my $Search = $_[0];
20635 if($Search!~/inc/) {
20636 $HSearch = 0;
20637 }
20638 if($Search!~/lib/) {
20639 $LSearch = 0;
20640 }
20641 if($Search!~/bin/) {
20642 $BSearch = 0;
20643 }
20644 if($Search!~/gcc/) {
20645 $GSearch = 0;
20646 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020647 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020648 { # <search_headers> section of the XML descriptor
20649 # do NOT search for systems headers
20650 $HSearch = 0;
20651 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020652 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020653 { # <search_headers> section of the XML descriptor
20654 # do NOT search for systems headers
20655 $LSearch = 0;
20656 }
20657 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20658 { # additional search paths
20659 next if($Type eq "include" and not $HSearch);
20660 next if($Type eq "lib" and not $LSearch);
20661 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020662 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020663 }
20664 if($OSgroup ne "windows")
20665 { # unix-like
20666 foreach my $Type ("include", "lib", "bin")
20667 { # automatic detection of system "devel" directories
20668 next if($Type eq "include" and not $HSearch);
20669 next if($Type eq "lib" and not $LSearch);
20670 next if($Type eq "bin" and not $BSearch);
20671 my ($UsrDir, $RootDir) = ("/usr", "/");
20672 if($SystemRoot and $Type ne "bin")
20673 { # 1. search for target headers and libraries
20674 # 2. use host commands: ldconfig, readelf, etc.
20675 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20676 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020677 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020678 if(-d $RootDir."/".$Type)
20679 { # if "/lib" is symbolic link
20680 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020681 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020682 }
20683 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020684 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020685 }
20686 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020687 if(-d $UsrDir)
20688 {
20689 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020690 if(-d $UsrDir."/".$Type)
20691 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020692 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020693 }
20694 }
20695 }
20696 }
20697 if($BSearch)
20698 {
20699 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020700 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020701 }
20702 # check environment variables
20703 if($OSgroup eq "beos")
20704 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020705 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020706 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020707 if($_ eq ".") {
20708 next;
20709 }
20710 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20711 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20712 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020713 }
20714 }
20715 if($HSearch)
20716 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020717 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20718 split(/:|;/, $ENV{"BEINCLUDES"})
20719 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020720 }
20721 if($LSearch)
20722 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020723 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20724 split(/:|;/, $ENV{"BELIBRARIES"}),
20725 split(/:|;/, $ENV{"LIBRARY_PATH"})
20726 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020727 }
20728 }
20729 if($LSearch)
20730 { # using linker to get system paths
20731 if(my $LPaths = detect_lib_default_paths())
20732 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020733 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020734 foreach my $Name (keys(%{$LPaths}))
20735 {
20736 if($SystemRoot
20737 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20738 { # wrong ldconfig configuration
20739 # check your <sysroot>/etc/ld.so.conf
20740 next;
20741 }
20742 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020743 if(my $Dir = get_dirname($LPaths->{$Name})) {
20744 $Dirs{$Dir} = 1;
20745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020746 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020747 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020748 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020749 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020750 }
20751 if($BSearch)
20752 {
20753 if($CrossGcc)
20754 { # --cross-gcc=arm-linux-gcc
20755 if(-e $CrossGcc)
20756 { # absolute or relative path
20757 $GCC_PATH = get_abs_path($CrossGcc);
20758 }
20759 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20760 { # command name
20761 $GCC_PATH = $CrossGcc;
20762 }
20763 else {
20764 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20765 }
20766 if($GCC_PATH=~/\s/) {
20767 $GCC_PATH = "\"".$GCC_PATH."\"";
20768 }
20769 }
20770 }
20771 if($GSearch)
20772 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020773 if(not $CrossGcc)
20774 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020775 $GCC_PATH = get_CmdPath("gcc");
20776 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020777 if(not $GCC_PATH)
20778 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020779 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020780 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020781 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020782 { # select the latest version
20783 @GCCs = sort {$b cmp $a} @GCCs;
20784 if(check_gcc($GCCs[0], "3"))
20785 {
20786 $GCC_PATH = $GCCs[0];
20787 last;
20788 }
20789 }
20790 }
20791 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020792 if(not $GCC_PATH) {
20793 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20794 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020795
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020796 if(not $CheckObjectsOnly_Opt)
20797 {
20798 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
20799 {
20800 my $GccTarget = get_dumpmachine($GCC_PATH);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020801 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020802 if($GccTarget=~/symbian/)
20803 {
20804 $OStarget = "symbian";
20805 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20806 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020807
20808 # check GCC version
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020809 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020810 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040020811 # introduced in 4.8
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020812 # fixed in 4.8.3
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020813 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20814 $EMERGENCY_MODE_48 = 1;
20815 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020816 }
20817 else {
20818 exitStatus("Error", "something is going wrong with the GCC compiler");
20819 }
20820 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020821 if($HSearch)
20822 {
20823 if(not $NoStdInc)
20824 { # do NOT search in GCC standard paths
20825 my %DPaths = detect_inc_default_paths();
20826 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20827 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20828 @DefaultIncPaths = @{$DPaths{"Inc"}};
20829 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020830 }
20831 }
20832 }
20833 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020834 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020835 my $IncPath = "/usr/include";
20836 if($SystemRoot) {
20837 $IncPath = $SystemRoot.$IncPath;
20838 }
20839 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020840 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020841 }
20842 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020843
20844 if($ExtraInfo)
20845 {
20846 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20847 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20848 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020849}
20850
20851sub getLIB_EXT($)
20852{
20853 my $Target = $_[0];
20854 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20855 return $Ext;
20856 }
20857 return $OS_LibExt{$LIB_TYPE}{"default"};
20858}
20859
20860sub getAR_EXT($)
20861{
20862 my $Target = $_[0];
20863 if(my $Ext = $OS_Archive{$Target}) {
20864 return $Ext;
20865 }
20866 return $OS_Archive{"default"};
20867}
20868
20869sub get_dumpversion($)
20870{
20871 my $Cmd = $_[0];
20872 return "" if(not $Cmd);
20873 if($Cache{"get_dumpversion"}{$Cmd}) {
20874 return $Cache{"get_dumpversion"}{$Cmd};
20875 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020876 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020877 chomp($V);
20878 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20879}
20880
20881sub get_dumpmachine($)
20882{
20883 my $Cmd = $_[0];
20884 return "" if(not $Cmd);
20885 if($Cache{"get_dumpmachine"}{$Cmd}) {
20886 return $Cache{"get_dumpmachine"}{$Cmd};
20887 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020888 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020889 chomp($Machine);
20890 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20891}
20892
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020893sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020894{
20895 my $Cmd = $_[0];
20896 return "" if(not $Cmd);
20897 my @Options = (
20898 "--version",
20899 "-help"
20900 );
20901 foreach my $Opt (@Options)
20902 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020903 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020904 if($Info) {
20905 return 1;
20906 }
20907 }
20908 return 0;
20909}
20910
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020911sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020912{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020913 my ($Cmd, $ReqVer) = @_;
20914 return 0 if(not $Cmd or not $ReqVer);
20915 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20916 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020917 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020918 if(my $GccVer = get_dumpversion($Cmd))
20919 {
20920 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20921 if(cmpVersions($GccVer, $ReqVer)>=0) {
20922 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20923 }
20924 }
20925 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020926}
20927
20928sub get_depth($)
20929{
20930 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020931 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020932 }
20933 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20934}
20935
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020936sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020937{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020938 return if($Cache{"registerGccHeaders"}); # this function should be called once
20939
20940 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020941 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020942 my @Headers = cmd_find($Path,"f");
20943 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20944 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020945 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020946 my $FileName = get_filename($HPath);
20947 if(not defined $DefaultGccHeader{$FileName})
20948 { # skip duplicated
20949 $DefaultGccHeader{$FileName} = $HPath;
20950 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020951 }
20952 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020953 $Cache{"registerGccHeaders"} = 1;
20954}
20955
20956sub registerCppHeaders()
20957{
20958 return if($Cache{"registerCppHeaders"}); # this function should be called once
20959
20960 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020961 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020962 my @Headers = cmd_find($CppDir,"f");
20963 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20964 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020965 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020966 my $FileName = get_filename($Path);
20967 if(not defined $DefaultCppHeader{$FileName})
20968 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020969 $DefaultCppHeader{$FileName} = $Path;
20970 }
20971 }
20972 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020973 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020974}
20975
20976sub parse_libname($$$)
20977{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020978 return "" if(not $_[0]);
20979 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20980 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020981 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020982 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20983}
20984
20985sub parse_libname_I($$$)
20986{
20987 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020988
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020989 if($Target eq "symbian") {
20990 return parse_libname_symbian($Name, $Type);
20991 }
20992 elsif($Target eq "windows") {
20993 return parse_libname_windows($Name, $Type);
20994 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020995
20996 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020997 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020998 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020999 { # libSDL-1.2.so.0.7.1
21000 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021001 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021002 if($Type eq "name")
21003 { # libSDL-1.2
21004 # libwbxml2
21005 return $2;
21006 }
21007 elsif($Type eq "name+ext")
21008 { # libSDL-1.2.so
21009 # libwbxml2.so
21010 return $1;
21011 }
21012 elsif($Type eq "version")
21013 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021014 if(defined $7
21015 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021016 { # 0.7.1
21017 return $7;
21018 }
21019 else
21020 { # libc-2.5.so (=>2.5 version)
21021 my $MV = $5;
21022 $MV=~s/\A[\-\_]+//g;
21023 return $MV;
21024 }
21025 }
21026 elsif($Type eq "short")
21027 { # libSDL
21028 # libwbxml2
21029 return $3;
21030 }
21031 elsif($Type eq "shortest")
21032 { # SDL
21033 # wbxml
21034 return shortest_name($3);
21035 }
21036 }
21037 return "";# error
21038}
21039
21040sub parse_libname_symbian($$)
21041{
21042 my ($Name, $Type) = @_;
21043 my $Ext = getLIB_EXT("symbian");
21044 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21045 { # libpthread{00010001}.dso
21046 if($Type eq "name")
21047 { # libpthread{00010001}
21048 return $2;
21049 }
21050 elsif($Type eq "name+ext")
21051 { # libpthread{00010001}.dso
21052 return $1;
21053 }
21054 elsif($Type eq "version")
21055 { # 00010001
21056 my $V = $4;
21057 $V=~s/\{(.+)\}/$1/;
21058 return $V;
21059 }
21060 elsif($Type eq "short")
21061 { # libpthread
21062 return $3;
21063 }
21064 elsif($Type eq "shortest")
21065 { # pthread
21066 return shortest_name($3);
21067 }
21068 }
21069 return "";# error
21070}
21071
21072sub parse_libname_windows($$)
21073{
21074 my ($Name, $Type) = @_;
21075 my $Ext = getLIB_EXT("windows");
21076 if($Name=~/((.+?)\.$Ext)\Z/)
21077 { # netapi32.dll
21078 if($Type eq "name")
21079 { # netapi32
21080 return $2;
21081 }
21082 elsif($Type eq "name+ext")
21083 { # netapi32.dll
21084 return $1;
21085 }
21086 elsif($Type eq "version")
21087 { # DLL version embedded
21088 # at binary-level
21089 return "";
21090 }
21091 elsif($Type eq "short")
21092 { # netapi32
21093 return $2;
21094 }
21095 elsif($Type eq "shortest")
21096 { # netapi
21097 return shortest_name($2);
21098 }
21099 }
21100 return "";# error
21101}
21102
21103sub shortest_name($)
21104{
21105 my $Name = $_[0];
21106 # remove prefix
21107 $Name=~s/\A(lib|open)//;
21108 # remove suffix
21109 $Name=~s/[\W\d_]+\Z//i;
21110 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21111 return $Name;
21112}
21113
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021114sub createSymbolsList($$$$$)
21115{
21116 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
21117 read_ABI_Dump(1, $DPath);
21118 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021119 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021120 }
21121 my %SymbolHeaderLib = ();
21122 my $Total = 0;
21123 # Get List
21124 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21125 {
21126 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021127 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021128 next;
21129 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021130 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021131 { # skip other symbols
21132 next;
21133 }
21134 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21135 if(not $HeaderName)
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 }
21139 my $DyLib = $Symbol_Library{1}{$Symbol};
21140 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021141 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021142 next;
21143 }
21144 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21145 $Total+=1;
21146 }
21147 # Draw List
21148 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21149 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21150 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21151 {
21152 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21153 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021154 my %NS_Symbol = ();
21155 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021156 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021157 }
21158 foreach my $NameSpace (sort keys(%NS_Symbol))
21159 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021160 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021161 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21162 foreach my $Symbol (@SortedInterfaces)
21163 {
21164 my $SubReport = "";
21165 my $Signature = get_Signature($Symbol, 1);
21166 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021167 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021168 }
21169 if($Symbol=~/\A(_Z|\?)/)
21170 {
21171 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021172 $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 +040021173 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021174 else {
21175 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21176 }
21177 }
21178 else
21179 {
21180 if($Signature) {
21181 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21182 }
21183 else {
21184 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21185 }
21186 }
21187 $SYMBOLS_LIST .= $SubReport;
21188 }
21189 }
21190 $SYMBOLS_LIST .= "<br/>\n";
21191 }
21192 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021193 # clear info
21194 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21195 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21196 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21197 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021198 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021199 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021200 my $CssStyles = readModule("Styles", "SymbolsList.css");
21201 my $JScripts = readModule("Scripts", "Sections.js");
21202 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021203 my $Title = "$LName: public symbols";
21204 my $Keywords = "$LName, API, symbols";
21205 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021206 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021207 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030021208 <br/><br/><hr/>\n".getReportFooter("Single")."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021209 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021210 writeFile($SaveTo, $SYMBOLS_LIST);
21211}
21212
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021213sub add_target_libs($)
21214{
21215 foreach (@{$_[0]}) {
21216 $TargetLibs{$_} = 1;
21217 }
21218}
21219
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021220sub is_target_lib($)
21221{
21222 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021223 if(not $LName) {
21224 return 0;
21225 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021226 if($TargetLibraryName
21227 and $LName!~/\Q$TargetLibraryName\E/) {
21228 return 0;
21229 }
21230 if(keys(%TargetLibs)
21231 and not $TargetLibs{$LName}
21232 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21233 return 0;
21234 }
21235 return 1;
21236}
21237
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021238sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021239{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021240 my ($H, $V) = @_;
21241 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021242 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021243 if($TargetHeaders{$V}{$H}) {
21244 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021245 }
21246 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021247 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021248}
21249
21250sub checkVersionNum($$)
21251{
21252 my ($LibVersion, $Path) = @_;
21253 if(my $VerNum = $TargetVersion{$LibVersion}) {
21254 return $VerNum;
21255 }
21256 my $UsedAltDescr = 0;
21257 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021258 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021259 next if(isDump($Part)); # ABI dump
21260 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021261 my $VerNum = "";
21262 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021263 {
21264 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021265 $VerNum = parse_libname($Part, "version", $OStarget);
21266 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021267 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021268 }
21269 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021270 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
21271 {
21272 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021273 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021274 }
21275 if($VerNum ne "")
21276 {
21277 $TargetVersion{$LibVersion} = $VerNum;
21278 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021279 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021280 }
21281 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021282 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 +040021283 }
21284 return $TargetVersion{$LibVersion};
21285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021286 }
21287 if($UsedAltDescr)
21288 {
21289 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021290 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021291 }
21292 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021293 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021294 }
21295 }
21296}
21297
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021298sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021299{
21300 my $Str = $_[0];
21301 return "" if(not $Str);
21302 $Str=~s/\Q$TargetLibraryName\E//g;
21303 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021304 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021305 return $2;
21306 }
21307 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
21308 return $V;
21309 }
21310 return "";
21311}
21312
21313sub readLibs($)
21314{
21315 my $LibVersion = $_[0];
21316 if($OStarget eq "windows")
21317 { # dumpbin.exe will crash
21318 # without VS Environment
21319 check_win32_env();
21320 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021321 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021322 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021323 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021324}
21325
21326sub dump_sorting($)
21327{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021328 my $Hash = $_[0];
21329 return [] if(not $Hash);
21330 my @Keys = keys(%{$Hash});
21331 return [] if($#Keys<0);
21332 if($Keys[0]=~/\A\d+\Z/)
21333 { # numbers
21334 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021335 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021336 else
21337 { # strings
21338 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021339 }
21340}
21341
21342sub printMsg($$)
21343{
21344 my ($Type, $Msg) = @_;
21345 if($Type!~/\AINFO/) {
21346 $Msg = $Type.": ".$Msg;
21347 }
21348 if($Type!~/_C\Z/) {
21349 $Msg .= "\n";
21350 }
21351 if($Quiet)
21352 { # --quiet option
21353 appendFile($COMMON_LOG_PATH, $Msg);
21354 }
21355 else
21356 {
21357 if($Type eq "ERROR") {
21358 print STDERR $Msg;
21359 }
21360 else {
21361 print $Msg;
21362 }
21363 }
21364}
21365
21366sub exitStatus($$)
21367{
21368 my ($Code, $Msg) = @_;
21369 printMsg("ERROR", $Msg);
21370 exit($ERROR_CODE{$Code});
21371}
21372
21373sub exitReport()
21374{ # the tool has run without any errors
21375 printReport();
21376 if($COMPILE_ERRORS)
21377 { # errors in headers may add false positives/negatives
21378 exit($ERROR_CODE{"Compile_Error"});
21379 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021380 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21381 { # --binary
21382 exit($ERROR_CODE{"Incompatible"});
21383 }
21384 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21385 { # --source
21386 exit($ERROR_CODE{"Incompatible"});
21387 }
21388 elsif($RESULT{"Source"}{"Problems"}
21389 or $RESULT{"Binary"}{"Problems"})
21390 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021391 exit($ERROR_CODE{"Incompatible"});
21392 }
21393 else {
21394 exit($ERROR_CODE{"Compatible"});
21395 }
21396}
21397
21398sub readRules($)
21399{
21400 my $Kind = $_[0];
21401 if(not -f $RULES_PATH{$Kind}) {
21402 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21403 }
21404 my $Content = readFile($RULES_PATH{$Kind});
21405 while(my $Rule = parseTag(\$Content, "rule"))
21406 {
21407 my $RId = parseTag(\$Rule, "id");
21408 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21409 foreach my $Prop (@Properties) {
21410 if(my $Value = parseTag(\$Rule, lc($Prop)))
21411 {
21412 $Value=~s/\n[ ]*//;
21413 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21414 }
21415 }
21416 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21417 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21418 }
21419 else {
21420 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21421 }
21422 }
21423}
21424
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021425sub getReportPath($)
21426{
21427 my $Level = $_[0];
21428 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21429 if($Level eq "Binary")
21430 {
21431 if($BinaryReportPath)
21432 { # --bin-report-path
21433 return $BinaryReportPath;
21434 }
21435 elsif($OutputReportPath)
21436 { # --report-path
21437 return $OutputReportPath;
21438 }
21439 else
21440 { # default
21441 return $Dir."/abi_compat_report.$ReportFormat";
21442 }
21443 }
21444 elsif($Level eq "Source")
21445 {
21446 if($SourceReportPath)
21447 { # --src-report-path
21448 return $SourceReportPath;
21449 }
21450 elsif($OutputReportPath)
21451 { # --report-path
21452 return $OutputReportPath;
21453 }
21454 else
21455 { # default
21456 return $Dir."/src_compat_report.$ReportFormat";
21457 }
21458 }
21459 else
21460 {
21461 if($OutputReportPath)
21462 { # --report-path
21463 return $OutputReportPath;
21464 }
21465 else
21466 { # default
21467 return $Dir."/compat_report.$ReportFormat";
21468 }
21469 }
21470}
21471
21472sub printStatMsg($)
21473{
21474 my $Level = $_[0];
21475 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21476}
21477
21478sub listAffected($)
21479{
21480 my $Level = $_[0];
21481 my $List = "";
21482 foreach (keys(%{$TotalAffected{$Level}}))
21483 {
21484 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21485 { # skip "Low"-severity problems
21486 next;
21487 }
21488 $List .= "$_\n";
21489 }
21490 my $Dir = get_dirname(getReportPath($Level));
21491 if($Level eq "Binary") {
21492 writeFile($Dir."/abi_affected.txt", $List);
21493 }
21494 elsif($Level eq "Source") {
21495 writeFile($Dir."/src_affected.txt", $List);
21496 }
21497}
21498
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021499sub printReport()
21500{
21501 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021502 createReport();
21503 if($JoinReport or $DoubleReport)
21504 {
21505 if($RESULT{"Binary"}{"Problems"}
21506 or $RESULT{"Source"}{"Problems"}) {
21507 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021508 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021509 else {
21510 printMsg("INFO", "result: COMPATIBLE");
21511 }
21512 printStatMsg("Binary");
21513 printStatMsg("Source");
21514 if($ListAffected)
21515 { # --list-affected
21516 listAffected("Binary");
21517 listAffected("Source");
21518 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021519 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021520 elsif($BinaryOnly)
21521 {
21522 if($RESULT{"Binary"}{"Problems"}) {
21523 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21524 }
21525 else {
21526 printMsg("INFO", "result: COMPATIBLE");
21527 }
21528 printStatMsg("Binary");
21529 if($ListAffected)
21530 { # --list-affected
21531 listAffected("Binary");
21532 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021533 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021534 elsif($SourceOnly)
21535 {
21536 if($RESULT{"Source"}{"Problems"}) {
21537 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21538 }
21539 else {
21540 printMsg("INFO", "result: COMPATIBLE");
21541 }
21542 printStatMsg("Source");
21543 if($ListAffected)
21544 { # --list-affected
21545 listAffected("Source");
21546 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021547 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021548 if($StdOut)
21549 {
21550 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021551 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021552 printMsg("INFO", "compatibility report has been generated to stdout");
21553 }
21554 else
21555 { # default
21556 printMsg("INFO", "compatibility reports have been generated to stdout");
21557 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021558 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021559 else
21560 {
21561 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021562 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021563 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21564 }
21565 elsif($DoubleReport)
21566 { # default
21567 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21568 }
21569 elsif($BinaryOnly)
21570 { # --binary
21571 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21572 }
21573 elsif($SourceOnly)
21574 { # --source
21575 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021577 }
21578}
21579
21580sub check_win32_env()
21581{
21582 if(not $ENV{"DevEnvDir"}
21583 or not $ENV{"LIB"}) {
21584 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21585 }
21586}
21587
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021588sub diffSets($$)
21589{
21590 my ($S1, $S2) = @_;
21591 my @SK1 = keys(%{$S1});
21592 my @SK2 = keys(%{$S2});
21593 if($#SK1!=$#SK2) {
21594 return 1;
21595 }
21596 foreach my $K1 (@SK1)
21597 {
21598 if(not defined $S2->{$K1}) {
21599 return 1;
21600 }
21601 }
21602 return 0;
21603}
21604
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021605sub defaultDumpPath($$)
21606{
21607 my ($N, $V) = @_;
21608 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21609}
21610
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021611sub create_ABI_Dump()
21612{
21613 if(not -e $DumpAPI) {
21614 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21615 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021616
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021617 my @DParts = split(/\s*,\s*/, $DumpAPI);
21618 foreach my $Part (@DParts)
21619 {
21620 if(not -e $Part) {
21621 exitStatus("Access_Error", "can't access \'$Part\'");
21622 }
21623 }
21624 checkVersionNum(1, $DumpAPI);
21625 foreach my $Part (@DParts)
21626 {
21627 if(isDump($Part)) {
21628 read_ABI_Dump(1, $Part);
21629 }
21630 else {
21631 readDescriptor(1, createDescriptor(1, $Part));
21632 }
21633 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021634
21635 if(not $Descriptor{1}{"Version"})
21636 { # set to default: X
21637 $Descriptor{1}{"Version"} = "X";
21638 }
21639
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021640 initLogging(1);
21641 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021642
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021643 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021644 if($OutputDumpPath)
21645 { # user defined path
21646 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021647 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021648 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21649
21650 if(not $Archive and not $StdOut)
21651 { # check archive utilities
21652 if($OSgroup eq "windows")
21653 { # using zip
21654 my $ZipCmd = get_CmdPath("zip");
21655 if(not $ZipCmd) {
21656 exitStatus("Not_Found", "can't find \"zip\"");
21657 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021658 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021659 else
21660 { # using tar and gzip
21661 my $TarCmd = get_CmdPath("tar");
21662 if(not $TarCmd) {
21663 exitStatus("Not_Found", "can't find \"tar\"");
21664 }
21665 my $GzipCmd = get_CmdPath("gzip");
21666 if(not $GzipCmd) {
21667 exitStatus("Not_Found", "can't find \"gzip\"");
21668 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021669 }
21670 }
21671
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021672 if(not $Descriptor{1}{"Dump"})
21673 {
21674 if(not $CheckHeadersOnly) {
21675 readLibs(1);
21676 }
21677 if($CheckHeadersOnly) {
21678 setLanguage(1, "C++");
21679 }
21680 if(not $CheckObjectsOnly) {
21681 searchForHeaders(1);
21682 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021683 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021684 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021685 if(not $Descriptor{1}{"Dump"})
21686 {
21687 if($Descriptor{1}{"Headers"}) {
21688 readHeaders(1);
21689 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021690 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021691 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021692 if(not keys(%{$SymbolInfo{1}}))
21693 { # check if created dump is valid
21694 if(not $ExtendedCheck and not $CheckObjectsOnly)
21695 {
21696 if($CheckHeadersOnly) {
21697 exitStatus("Empty_Set", "the set of public symbols is empty");
21698 }
21699 else {
21700 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21701 }
21702 }
21703 }
21704 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021705 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021706 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21707 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021708 if($ExtraDump)
21709 { # add unmangled names to the ABI dump
21710 my @Names = ();
21711 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21712 {
21713 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21714 push(@Names, $MnglName);
21715 }
21716 }
21717 translateSymbols(@Names, 1);
21718 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21719 {
21720 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21721 {
21722 if(my $Unmangled = $tr_name{$MnglName})
21723 {
21724 if($MnglName ne $Unmangled) {
21725 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21726 }
21727 }
21728 }
21729 }
21730 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021731
21732 my %GccConstants = (); # built-in GCC constants
21733 foreach my $Name (keys(%{$Constants{1}}))
21734 {
21735 if(not defined $Constants{1}{$Name}{"Header"})
21736 {
21737 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21738 delete($Constants{1}{$Name});
21739 }
21740 }
21741
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021742 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021743 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021744 "TypeInfo" => $TypeInfo{1},
21745 "SymbolInfo" => $SymbolInfo{1},
21746 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021747 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021748 "SymbolVersion" => $SymVer{1},
21749 "LibraryVersion" => $Descriptor{1}{"Version"},
21750 "LibraryName" => $TargetLibraryName,
21751 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021752 "SkipTypes" => $SkipTypes{1},
21753 "SkipSymbols" => $SkipSymbols{1},
21754 "SkipNameSpaces" => $SkipNameSpaces{1},
21755 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021756 "Headers" => \%HeadersInfo,
21757 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021758 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021759 "NameSpaces" => $NestedNameSpaces{1},
21760 "Target" => $OStarget,
21761 "Arch" => getArch(1),
21762 "WordSize" => $WORD_SIZE{1},
21763 "GccVersion" => get_dumpversion($GCC_PATH),
21764 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21765 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21766 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021767 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021768 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021769 }
21770 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021771 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021772 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021773 if($ExtendedCheck)
21774 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021775 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021776 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021777 if($BinaryOnly)
21778 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021779 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021780 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021781 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021782 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021783 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021784 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21785 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021786 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021787
21788 my $ABI_DUMP = "";
21789 if($UseXML)
21790 {
21791 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021792 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021793 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021794 else
21795 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021796 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021797 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021798 if($StdOut)
21799 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021800 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021801 printMsg("INFO", "ABI dump has been generated to stdout");
21802 return;
21803 }
21804 else
21805 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021806 my ($DDir, $DName) = separate_path($DumpPath);
21807 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021808 if(not $Archive) {
21809 $DPath = $DumpPath;
21810 }
21811
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021812 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021813
21814 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021815 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021816 close(DUMP);
21817
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021818 if(not -s $DPath) {
21819 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21820 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021821 if($Archive) {
21822 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021823 }
21824
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021825 if($OutputDumpPath) {
21826 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021827 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021828 else {
21829 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21830 }
21831 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 +040021832 }
21833}
21834
21835sub quickEmptyReports()
21836{ # Quick "empty" reports
21837 # 4 times faster than merging equal dumps
21838 # NOTE: the dump contains the "LibraryVersion" attribute
21839 # if you change the version, then your dump will be different
21840 # OVERCOME: use -v1 and v2 options for comparing dumps
21841 # and don't change version in the XML descriptor (and dumps)
21842 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21843 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21844 {
21845 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21846 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21847 if($FilePath1 and $FilePath2)
21848 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021849 my $Line = readLineNum($FilePath1, 0);
21850 if($Line=~/xml/)
21851 { # XML format
21852 # is not supported yet
21853 return;
21854 }
21855
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021856 local $/ = undef;
21857
21858 open(DUMP1, $FilePath1);
21859 my $Content1 = <DUMP1>;
21860 close(DUMP1);
21861
21862 open(DUMP2, $FilePath2);
21863 my $Content2 = <DUMP2>;
21864 close(DUMP2);
21865
21866 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021867 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021868 # clean memory
21869 undef $Content2;
21870
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021871 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021872 my $ABIdump = eval($Content1);
21873
21874 # clean memory
21875 undef $Content1;
21876
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021877 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021878 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 +040021879 }
21880 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021881 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021882 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21883 }
21884 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021885 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021886 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21887 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021888 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021889 read_Libs_DumpInfo($ABIdump, 1);
21890 read_Machine_DumpInfo($ABIdump, 1);
21891 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021892
21893 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21894 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21895
21896 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21897 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21898
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021899 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21900 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21901 exitReport();
21902 }
21903 }
21904 }
21905}
21906
21907sub initLogging($)
21908{
21909 my $LibVersion = $_[0];
21910 # create log directory
21911 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21912 if($OutputLogPath{$LibVersion})
21913 { # user-defined by -log-path option
21914 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21915 }
21916 if($LogMode ne "n") {
21917 mkpath($LOG_DIR);
21918 }
21919 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021920 if($Debug)
21921 { # debug directory
21922 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021923
21924 if(not $ExtraInfo)
21925 { # enable --extra-info
21926 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21927 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021928 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021929 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021930}
21931
21932sub writeLog($$)
21933{
21934 my ($LibVersion, $Msg) = @_;
21935 if($LogMode ne "n") {
21936 appendFile($LOG_PATH{$LibVersion}, $Msg);
21937 }
21938}
21939
21940sub resetLogging($)
21941{
21942 my $LibVersion = $_[0];
21943 if($LogMode!~/a|n/)
21944 { # remove old log
21945 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021946 if($Debug) {
21947 rmtree($DEBUG_PATH{$LibVersion});
21948 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021949 }
21950}
21951
21952sub printErrorLog($)
21953{
21954 my $LibVersion = $_[0];
21955 if($LogMode ne "n") {
21956 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21957 }
21958}
21959
21960sub isDump($)
21961{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021962 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
21963 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021964 return $1;
21965 }
21966 return 0;
21967}
21968
21969sub isDump_U($)
21970{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021971 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021972 return $1;
21973 }
21974 return 0;
21975}
21976
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021977sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021978{
21979 # read input XML descriptors or ABI dumps
21980 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021981 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021982 }
21983 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
21984 foreach my $Part (@DParts1)
21985 {
21986 if(not -e $Part) {
21987 exitStatus("Access_Error", "can't access \'$Part\'");
21988 }
21989 }
21990 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021991 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021992 }
21993 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
21994 foreach my $Part (@DParts2)
21995 {
21996 if(not -e $Part) {
21997 exitStatus("Access_Error", "can't access \'$Part\'");
21998 }
21999 }
22000 detect_default_paths("bin"); # to extract dumps
22001 if($#DParts1==0 and $#DParts2==0
22002 and isDump($Descriptor{1}{"Path"})
22003 and isDump($Descriptor{2}{"Path"}))
22004 { # optimization: equal ABI dumps
22005 quickEmptyReports();
22006 }
22007 checkVersionNum(1, $Descriptor{1}{"Path"});
22008 checkVersionNum(2, $Descriptor{2}{"Path"});
22009 printMsg("INFO", "preparation, please wait ...");
22010 foreach my $Part (@DParts1)
22011 {
22012 if(isDump($Part)) {
22013 read_ABI_Dump(1, $Part);
22014 }
22015 else {
22016 readDescriptor(1, createDescriptor(1, $Part));
22017 }
22018 }
22019 foreach my $Part (@DParts2)
22020 {
22021 if(isDump($Part)) {
22022 read_ABI_Dump(2, $Part);
22023 }
22024 else {
22025 readDescriptor(2, createDescriptor(2, $Part));
22026 }
22027 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022028
22029 if(not $Descriptor{1}{"Version"})
22030 { # set to default: X
22031 $Descriptor{1}{"Version"} = "X";
22032 }
22033
22034 if(not $Descriptor{2}{"Version"})
22035 { # set to default: Y
22036 $Descriptor{2}{"Version"} = "Y";
22037 }
22038
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022039 initLogging(1);
22040 initLogging(2);
22041 # check consistency
22042 if(not $Descriptor{1}{"Headers"}
22043 and not $Descriptor{1}{"Libs"}) {
22044 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
22045 }
22046 if(not $Descriptor{2}{"Headers"}
22047 and not $Descriptor{2}{"Libs"}) {
22048 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
22049 }
22050 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
22051 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
22052 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
22053 }
22054 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
22055 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
22056 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
22057 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022058 if(not $Descriptor{1}{"Headers"})
22059 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022060 if($CheckHeadersOnly_Opt) {
22061 exitStatus("Error", "can't find header files info in descriptor d1");
22062 }
22063 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022064 if(not $Descriptor{2}{"Headers"})
22065 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022066 if($CheckHeadersOnly_Opt) {
22067 exitStatus("Error", "can't find header files info in descriptor d2");
22068 }
22069 }
22070 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022071 or not $Descriptor{2}{"Headers"})
22072 {
22073 if(not $CheckObjectsOnly_Opt)
22074 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022075 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
22076 $CheckObjectsOnly = 1;
22077 }
22078 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022079 if(not $Descriptor{1}{"Libs"})
22080 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022081 if($CheckObjectsOnly_Opt) {
22082 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
22083 }
22084 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022085 if(not $Descriptor{2}{"Libs"})
22086 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022087 if($CheckObjectsOnly_Opt) {
22088 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
22089 }
22090 }
22091 if(not $Descriptor{1}{"Libs"}
22092 or not $Descriptor{2}{"Libs"})
22093 { # comparing standalone header files
22094 # comparing ABI dumps created with --headers-only
22095 if(not $CheckHeadersOnly_Opt)
22096 {
22097 printMsg("WARNING", "checking headers only");
22098 $CheckHeadersOnly = 1;
22099 }
22100 }
22101 if($UseDumps)
22102 { # --use-dumps
22103 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022104 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22105 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022106
22107 unlink($DumpPath1);
22108 unlink($DumpPath2);
22109
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022110 my $pid = fork();
22111 if($pid)
22112 { # dump on two CPU cores
22113 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22114 if($RelativeDirectory{1}) {
22115 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22116 }
22117 if($OutputLogPath{1}) {
22118 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22119 }
22120 if($CrossGcc) {
22121 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22122 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022123 if($Quiet)
22124 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022125 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022126 @PARAMS = (@PARAMS, "-logging-mode", "a");
22127 }
22128 elsif($LogMode and $LogMode ne "w")
22129 { # "w" is default
22130 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022131 }
22132 if($ExtendedCheck) {
22133 @PARAMS = (@PARAMS, "-extended");
22134 }
22135 if($UserLang) {
22136 @PARAMS = (@PARAMS, "-lang", $UserLang);
22137 }
22138 if($TargetVersion{1}) {
22139 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22140 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022141 if($BinaryOnly) {
22142 @PARAMS = (@PARAMS, "-binary");
22143 }
22144 if($SourceOnly) {
22145 @PARAMS = (@PARAMS, "-source");
22146 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022147 if($SortDump) {
22148 @PARAMS = (@PARAMS, "-sort");
22149 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022150 if($DumpFormat and $DumpFormat ne "perl") {
22151 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22152 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022153 if($CheckHeadersOnly) {
22154 @PARAMS = (@PARAMS, "-headers-only");
22155 }
22156 if($CheckObjectsOnly) {
22157 @PARAMS = (@PARAMS, "-objects-only");
22158 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022159 if($Debug)
22160 {
22161 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022162 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022163 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022164 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022165 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022166 exit(1);
22167 }
22168 }
22169 else
22170 { # child
22171 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22172 if($RelativeDirectory{2}) {
22173 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22174 }
22175 if($OutputLogPath{2}) {
22176 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22177 }
22178 if($CrossGcc) {
22179 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22180 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022181 if($Quiet)
22182 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022183 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022184 @PARAMS = (@PARAMS, "-logging-mode", "a");
22185 }
22186 elsif($LogMode and $LogMode ne "w")
22187 { # "w" is default
22188 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022189 }
22190 if($ExtendedCheck) {
22191 @PARAMS = (@PARAMS, "-extended");
22192 }
22193 if($UserLang) {
22194 @PARAMS = (@PARAMS, "-lang", $UserLang);
22195 }
22196 if($TargetVersion{2}) {
22197 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22198 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022199 if($BinaryOnly) {
22200 @PARAMS = (@PARAMS, "-binary");
22201 }
22202 if($SourceOnly) {
22203 @PARAMS = (@PARAMS, "-source");
22204 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022205 if($SortDump) {
22206 @PARAMS = (@PARAMS, "-sort");
22207 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022208 if($DumpFormat and $DumpFormat ne "perl") {
22209 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22210 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022211 if($CheckHeadersOnly) {
22212 @PARAMS = (@PARAMS, "-headers-only");
22213 }
22214 if($CheckObjectsOnly) {
22215 @PARAMS = (@PARAMS, "-objects-only");
22216 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022217 if($Debug)
22218 {
22219 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022220 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022222 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022223 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022224 exit(1);
22225 }
22226 else {
22227 exit(0);
22228 }
22229 }
22230 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022231
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022232 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022233 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22234 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022235 if($TargetTitle ne $TargetLibraryName) {
22236 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022237 }
22238 if($ShowRetVal) {
22239 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22240 }
22241 if($CrossGcc) {
22242 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22243 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022244 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22245 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022246 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022247 }
22248 if($ReportFormat and $ReportFormat ne "html")
22249 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022250 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22251 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022252 if($OutputReportPath) {
22253 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22254 }
22255 if($BinaryReportPath) {
22256 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22257 }
22258 if($SourceReportPath) {
22259 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22260 }
22261 if($LoggingPath) {
22262 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22263 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022264 if($CheckHeadersOnly) {
22265 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22266 }
22267 if($CheckObjectsOnly) {
22268 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
22269 }
22270 if($BinaryOnly) {
22271 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22272 }
22273 if($SourceOnly) {
22274 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22275 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022276 if($Debug)
22277 {
22278 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22279 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022280 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022281 system("perl", $0, @CMP_PARAMS);
22282 exit($?>>8);
22283 }
22284 if(not $Descriptor{1}{"Dump"}
22285 or not $Descriptor{2}{"Dump"})
22286 { # need GCC toolchain to analyze
22287 # header files and libraries
22288 detect_default_paths("inc|lib|gcc");
22289 }
22290 if(not $Descriptor{1}{"Dump"})
22291 {
22292 if(not $CheckHeadersOnly) {
22293 readLibs(1);
22294 }
22295 if($CheckHeadersOnly) {
22296 setLanguage(1, "C++");
22297 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022298 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022299 searchForHeaders(1);
22300 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022301 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022302 }
22303 if(not $Descriptor{2}{"Dump"})
22304 {
22305 if(not $CheckHeadersOnly) {
22306 readLibs(2);
22307 }
22308 if($CheckHeadersOnly) {
22309 setLanguage(2, "C++");
22310 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022311 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022312 searchForHeaders(2);
22313 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022314 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022315 }
22316 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22317 { # support for old ABI dumps
22318 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022319 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022320 {
22321 $WORD_SIZE{1} = $WORD_SIZE{2};
22322 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22323 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022324 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022325 {
22326 $WORD_SIZE{2} = $WORD_SIZE{1};
22327 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22328 }
22329 }
22330 elsif(not $WORD_SIZE{1}
22331 and not $WORD_SIZE{2})
22332 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022333 $WORD_SIZE{1} = "4";
22334 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022335 }
22336 if($Descriptor{1}{"Dump"})
22337 { # support for old ABI dumps
22338 prepareTypes(1);
22339 }
22340 if($Descriptor{2}{"Dump"})
22341 { # support for old ABI dumps
22342 prepareTypes(2);
22343 }
22344 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22345 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22346 }
22347 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022348 if(not $CheckObjectsOnly)
22349 {
22350 if($Descriptor{1}{"Headers"}
22351 and not $Descriptor{1}{"Dump"}) {
22352 readHeaders(1);
22353 }
22354 if($Descriptor{2}{"Headers"}
22355 and not $Descriptor{2}{"Dump"}) {
22356 readHeaders(2);
22357 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022358 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022359
22360 # clean memory
22361 %SystemHeaders = ();
22362 %mangled_name_gcc = ();
22363
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022364 prepareSymbols(1);
22365 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022366
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022367 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022368 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022369
22370 # Virtual Tables
22371 registerVTable(1);
22372 registerVTable(2);
22373
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022374 if(not checkDump(1, "1.22")
22375 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022376 { # support for old ABI dumps
22377 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22378 {
22379 if($ClassName=~/</)
22380 { # templates
22381 if(not defined $VirtualTable{1}{$ClassName})
22382 { # synchronize
22383 delete($VirtualTable{2}{$ClassName});
22384 }
22385 }
22386 }
22387 }
22388
22389 registerOverriding(1);
22390 registerOverriding(2);
22391
22392 setVirtFuncPositions(1);
22393 setVirtFuncPositions(2);
22394
22395 # Other
22396 addParamNames(1);
22397 addParamNames(2);
22398
22399 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022400}
22401
22402sub compareAPIs($)
22403{
22404 my $Level = $_[0];
22405 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022406 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022407 if($Level eq "Binary") {
22408 printMsg("INFO", "comparing ABIs ...");
22409 }
22410 else {
22411 printMsg("INFO", "comparing APIs ...");
22412 }
22413 if($CheckHeadersOnly
22414 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022415 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022416 detectAdded_H($Level);
22417 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022418 }
22419 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022420 { # added/removed in libs
22421 detectAdded($Level);
22422 detectRemoved($Level);
22423 }
22424 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022425 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022426 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022427 if(keys(%{$CheckedSymbols{$Level}})) {
22428 mergeConstants($Level);
22429 }
22430 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022431
22432 $Cache{"mergeTypes"} = (); # free memory
22433
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022434 if($CheckHeadersOnly
22435 or $Level eq "Source")
22436 { # added/removed in headers
22437 mergeHeaders($Level);
22438 }
22439 else
22440 { # added/removed in libs
22441 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022442 }
22443}
22444
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022445sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022446{
22447 my %Opts = (
22448 "OStarget"=>$OStarget,
22449 "Debug"=>$Debug,
22450 "Quiet"=>$Quiet,
22451 "LogMode"=>$LogMode,
22452 "CheckHeadersOnly"=>$CheckHeadersOnly,
22453
22454 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022455 "GCC_PATH"=>$GCC_PATH,
22456 "TargetSysInfo"=>$TargetSysInfo,
22457 "CrossPrefix"=>$CrossPrefix,
22458 "TargetLibraryName"=>$TargetLibraryName,
22459 "CrossGcc"=>$CrossGcc,
22460 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022461 "NoStdInc"=>$NoStdInc,
22462
22463 "BinaryOnly" => $BinaryOnly,
22464 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022465 );
22466 return \%Opts;
22467}
22468
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022469sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022470{
22471 my %CODE_ERROR = reverse(%ERROR_CODE);
22472 return $CODE_ERROR{$_[0]};
22473}
22474
22475sub scenario()
22476{
22477 if($StdOut)
22478 { # enable quiet mode
22479 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022480 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022481 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022482 if(not $LogMode)
22483 { # default
22484 $LogMode = "w";
22485 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022486 if($UserLang)
22487 { # --lang=C++
22488 $UserLang = uc($UserLang);
22489 $COMMON_LANGUAGE{1}=$UserLang;
22490 $COMMON_LANGUAGE{2}=$UserLang;
22491 }
22492 if($LoggingPath)
22493 {
22494 $OutputLogPath{1} = $LoggingPath;
22495 $OutputLogPath{2} = $LoggingPath;
22496 if($Quiet) {
22497 $COMMON_LOG_PATH = $LoggingPath;
22498 }
22499 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022500 if($Quick) {
22501 $ADD_TMPL_INSTANCES = 0;
22502 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022503 if($OutputDumpPath)
22504 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022505 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022506 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22507 }
22508 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022509 if($BinaryOnly and $SourceOnly)
22510 { # both --binary and --source
22511 # is the default mode
22512 $DoubleReport = 1;
22513 $JoinReport = 0;
22514 $BinaryOnly = 0;
22515 $SourceOnly = 0;
22516 if($OutputReportPath)
22517 { # --report-path
22518 $DoubleReport = 0;
22519 $JoinReport = 1;
22520 }
22521 }
22522 elsif($BinaryOnly or $SourceOnly)
22523 { # --binary or --source
22524 $DoubleReport = 0;
22525 $JoinReport = 0;
22526 }
22527 if($UseXML)
22528 { # --xml option
22529 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022530 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022531 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022532 if($ReportFormat)
22533 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022534 $ReportFormat = lc($ReportFormat);
22535 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022536 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022537 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022538 if($ReportFormat eq "htm")
22539 { # HTM == HTML
22540 $ReportFormat = "html";
22541 }
22542 elsif($ReportFormat eq "xml")
22543 { # --report-format=XML equal to --xml
22544 $UseXML = 1;
22545 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022546 }
22547 else
22548 { # default: HTML
22549 $ReportFormat = "html";
22550 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022551 if($DumpFormat)
22552 { # validate
22553 $DumpFormat = lc($DumpFormat);
22554 if($DumpFormat!~/\A(xml|perl)\Z/) {
22555 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22556 }
22557 if($DumpFormat eq "xml")
22558 { # --dump-format=XML equal to --xml
22559 $UseXML = 1;
22560 }
22561 }
22562 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022563 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022564 $DumpFormat = "perl";
22565 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022566 if($Quiet and $LogMode!~/a|n/)
22567 { # --quiet log
22568 if(-f $COMMON_LOG_PATH) {
22569 unlink($COMMON_LOG_PATH);
22570 }
22571 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022572 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022573 $CheckUndefined = 1;
22574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022575 if($TestTool and $UseDumps)
22576 { # --test && --use-dumps == --test-dump
22577 $TestDump = 1;
22578 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022579 if($Tolerant)
22580 { # enable all
22581 $Tolerance = 1234;
22582 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022583 if($Help)
22584 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022585 HELP_MESSAGE();
22586 exit(0);
22587 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022588 if($InfoMsg)
22589 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022590 INFO_MESSAGE();
22591 exit(0);
22592 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022593 if($ShowVersion)
22594 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022595 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 +040022596 exit(0);
22597 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022598 if($DumpVersion)
22599 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022600 printMsg("INFO", $TOOL_VERSION);
22601 exit(0);
22602 }
22603 if($ExtendedCheck) {
22604 $CheckHeadersOnly = 1;
22605 }
22606 if($SystemRoot_Opt)
22607 { # user defined root
22608 if(not -e $SystemRoot_Opt) {
22609 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22610 }
22611 $SystemRoot = $SystemRoot_Opt;
22612 $SystemRoot=~s/[\/]+\Z//g;
22613 if($SystemRoot) {
22614 $SystemRoot = get_abs_path($SystemRoot);
22615 }
22616 }
22617 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022618
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022619 if($SortDump)
22620 {
22621 $Data::Dumper::Useperl = 1;
22622 $Data::Dumper::Sortkeys = \&dump_sorting;
22623 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022624
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022625 if($TargetLibsPath)
22626 {
22627 if(not -f $TargetLibsPath) {
22628 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22629 }
22630 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22631 $TargetLibs{$Lib} = 1;
22632 }
22633 }
22634 if($TargetHeadersPath)
22635 { # --headers-list
22636 if(not -f $TargetHeadersPath) {
22637 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22638 }
22639 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22640 {
22641 $TargetHeaders{1}{$Header} = 1;
22642 $TargetHeaders{2}{$Header} = 1;
22643 }
22644 }
22645 if($TargetHeader)
22646 { # --header
22647 $TargetHeaders{1}{$TargetHeader} = 1;
22648 $TargetHeaders{2}{$TargetHeader} = 1;
22649 }
22650 if($TestTool
22651 or $TestDump)
22652 { # --test, --test-dump
22653 detect_default_paths("bin|gcc"); # to compile libs
22654 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022655 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022656 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022657 exit(0);
22658 }
22659 if($DumpSystem)
22660 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022661
22662 if(not $TargetSysInfo) {
22663 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22664 }
22665
22666 if(not -d $TargetSysInfo) {
22667 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22668 }
22669
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022670 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022671 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022672 { # system XML descriptor
22673 if(not -f $DumpSystem) {
22674 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22675 }
22676 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022677 foreach (@{$Ret->{"Tools"}})
22678 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022679 push_U($SystemPaths{"bin"}, $_);
22680 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022681 }
22682 if($Ret->{"CrossPrefix"}) {
22683 $CrossPrefix = $Ret->{"CrossPrefix"};
22684 }
22685 }
22686 elsif($SystemRoot_Opt)
22687 { # -sysroot "/" option
22688 # default target: /usr/lib, /usr/include
22689 # search libs: /usr/lib and /lib
22690 if(not -e $SystemRoot."/usr/lib") {
22691 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22692 }
22693 if(not -e $SystemRoot."/lib") {
22694 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22695 }
22696 if(not -e $SystemRoot."/usr/include") {
22697 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22698 }
22699 readSystemDescriptor("
22700 <name>
22701 $DumpSystem
22702 </name>
22703 <headers>
22704 $SystemRoot/usr/include
22705 </headers>
22706 <libs>
22707 $SystemRoot/usr/lib
22708 </libs>
22709 <search_libs>
22710 $SystemRoot/lib
22711 </search_libs>");
22712 }
22713 else {
22714 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22715 }
22716 detect_default_paths("bin|gcc"); # to check symbols
22717 if($OStarget eq "windows")
22718 { # to run dumpbin.exe
22719 # and undname.exe
22720 check_win32_env();
22721 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022722 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022723 exit(0);
22724 }
22725 if($CmpSystems)
22726 { # --cmp-systems
22727 detect_default_paths("bin"); # to extract dumps
22728 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022729 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022730 exit(0);
22731 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022732 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022733 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022734 }
22735 else
22736 { # validate library name
22737 if($TargetLibraryName=~/[\*\/\\]/) {
22738 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22739 }
22740 }
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022741 if(not $TargetTitle) {
22742 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022743 }
22744 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
22745 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
22746 }
22747 if($SymbolsListPath)
22748 {
22749 if(not -f $SymbolsListPath) {
22750 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22751 }
22752 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22753 $SymbolsList{$Interface} = 1;
22754 }
22755 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022756 if($TypesListPath)
22757 {
22758 if(not -f $TypesListPath) {
22759 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22760 }
22761 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22762 $TypesList{$Type} = 1;
22763 }
22764 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022765 if($SkipSymbolsListPath)
22766 {
22767 if(not -f $SkipSymbolsListPath) {
22768 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22769 }
22770 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022771 $SkipSymbols{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022772 }
22773 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022774 if($SkipHeadersPath)
22775 {
22776 if(not -f $SkipHeadersPath) {
22777 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22778 }
22779 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022780 { # register for both versions
22781 $SkipHeadersList{1}{$Path} = 1;
22782 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022783 my ($CPath, $Type) = classifyPath($Path);
22784 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022785 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022786 }
22787 }
22788 if($ParamNamesPath)
22789 {
22790 if(not -f $ParamNamesPath) {
22791 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22792 }
22793 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22794 {
22795 if($Line=~s/\A(\w+)\;//)
22796 {
22797 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022798 if($Line=~/;(\d+);/)
22799 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022800 while($Line=~s/(\d+);(\w+)//) {
22801 $AddIntParams{$Interface}{$1}=$2;
22802 }
22803 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022804 else
22805 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022806 my $Num = 0;
22807 foreach my $Name (split(/;/, $Line)) {
22808 $AddIntParams{$Interface}{$Num++}=$Name;
22809 }
22810 }
22811 }
22812 }
22813 }
22814 if($AppPath)
22815 {
22816 if(not -f $AppPath) {
22817 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22818 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022819 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022820 $SymbolsList_App{$Interface} = 1;
22821 }
22822 }
22823 if($DumpAPI)
22824 { # --dump-abi
22825 # make an API dump
22826 create_ABI_Dump();
22827 exit($COMPILE_ERRORS);
22828 }
22829 # default: compare APIs
22830 # -d1 <path>
22831 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022832 compareInit();
22833 if($JoinReport or $DoubleReport)
22834 {
22835 compareAPIs("Binary");
22836 compareAPIs("Source");
22837 }
22838 elsif($BinaryOnly) {
22839 compareAPIs("Binary");
22840 }
22841 elsif($SourceOnly) {
22842 compareAPIs("Source");
22843 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022844 exitReport();
22845}
22846
22847scenario();