blob: 213640cee4632016327b668b044974f378357f45 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03003# ABI Compliance Checker (ABICC) 1.99.10
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004# A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005#
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006# Copyright (C) 2009-2011 Institute for System Programming, RAS
7# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03008# Copyright (C) 2012-2013 ROSA Laboratory
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +03009# Copyright (C) 2013-2015 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010#
11# Written by Andrey Ponomarenko
12#
13# PLATFORMS
14# =========
15# Linux, FreeBSD, Mac OS X, Haiku, MS Windows, Symbian
16#
17# REQUIREMENTS
18# ============
19# Linux
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040020# - G++ (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021# - GNU Binutils (readelf, c++filt, objdump)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022# - Perl 5 (5.8 or newer)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040024#
25# Mac OS X
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040026# - Xcode (g++, c++filt, otool, nm)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040027# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040028#
29# MS Windows
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040030# - MinGW (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040031# - MS Visual C++ (dumpbin, undname, cl)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040032# - Active Perl 5 (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040033# - Sigcheck v1.71 or newer
34# - Info-ZIP 3.0 (zip, unzip)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040035# - Ctags (5.8 or newer)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040036# - Add tool locations to the PATH environment variable
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040037# - Run vsvars32.bat (C:\Microsoft Visual Studio 9.0\Common7\Tools\)
38#
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040039# COMPATIBILITY
40# =============
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030041# ABI Dumper >= 0.99.9
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040042#
43#
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040044# This program is free software: you can redistribute it and/or modify
45# it under the terms of the GNU General Public License or the GNU Lesser
46# General Public License as published by the Free Software Foundation.
47#
48# This program is distributed in the hope that it will be useful,
49# but WITHOUT ANY WARRANTY; without even the implied warranty of
50# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51# GNU General Public License for more details.
52#
53# You should have received a copy of the GNU General Public License
54# and the GNU Lesser General Public License along with this program.
55# If not, see <http://www.gnu.org/licenses/>.
56###########################################################################
57use Getopt::Long;
58Getopt::Long::Configure ("posix_default", "no_ignore_case");
59use File::Path qw(mkpath rmtree);
60use File::Temp qw(tempdir);
61use File::Copy qw(copy move);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040062use Cwd qw(abs_path cwd realpath);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040063use Storable qw(dclone);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040064use Data::Dumper;
Andrey Ponomarenko2fba6302012-03-29 17:44:47 +040065use Config;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040066
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030067my $TOOL_VERSION = "1.99.10";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040068my $ABI_DUMP_VERSION = "3.2";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040069my $XML_REPORT_VERSION = "1.2";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040070my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040071my $OSgroup = get_OSgroup();
72my $ORIG_DIR = cwd();
73my $TMP_DIR = tempdir(CLEANUP=>1);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030074my $LOCALE = "C.UTF-8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040075
76# Internal modules
77my $MODULES_DIR = get_Modules();
78push(@INC, get_dirname($MODULES_DIR));
79# Rules DB
80my %RULES_PATH = (
81 "Binary" => $MODULES_DIR."/RulesBin.xml",
82 "Source" => $MODULES_DIR."/RulesSrc.xml");
83
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030084my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040085$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030086$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
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400182GetOptions("h|help!" => \$Help,
183 "i|info!" => \$InfoMsg,
184 "v|version!" => \$ShowVersion,
185 "dumpversion!" => \$DumpVersion,
186# general options
187 "l|lib|library=s" => \$TargetLibraryName,
188 "d1|old|o=s" => \$Descriptor{1}{"Path"},
189 "d2|new|n=s" => \$Descriptor{2}{"Path"},
190 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400191# extra options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400192 "app|application=s" => \$AppPath,
193 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +0400194 "gcc-path|cross-gcc=s" => \$CrossGcc,
195 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
196 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400197 "sysroot=s" => \$SystemRoot_Opt,
198 "v1|version1|vnum=s" => \$TargetVersion{1},
199 "v2|version2=s" => \$TargetVersion{2},
200 "s|strict!" => \$StrictCompat,
201 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300202 "types-list=s" => \$TypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400203 "skip-symbols=s" => \$SkipSymbolsListPath,
204 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400205 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400206 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400207 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400208 "show-retval!" => \$ShowRetVal,
209 "use-dumps!" => \$UseDumps,
210 "nostdinc!" => \$NoStdInc,
211 "dump-system=s" => \$DumpSystem,
212 "sysinfo=s" => \$TargetSysInfo,
213 "cmp-systems!" => \$CmpSystems,
214 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400215 "ext|extended!" => \$ExtendedCheck,
216 "q|quiet!" => \$Quiet,
217 "stdout!" => \$StdOut,
218 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400219 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400220 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400221 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400222 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400223 "binary|bin|abi!" => \$BinaryOnly,
224 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400225 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400226# other options
227 "test!" => \$TestTool,
228 "test-dump!" => \$TestDump,
229 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400230 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400231 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400232 "p|params=s" => \$ParamNamesPath,
233 "relpath1|relpath=s" => \$RelativeDirectory{1},
234 "relpath2=s" => \$RelativeDirectory{2},
235 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400236 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400237 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400238 "bin-report-path=s" => \$BinaryReportPath,
239 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400240 "log-path=s" => \$LoggingPath,
241 "log1-path=s" => \$OutputLogPath{1},
242 "log2-path=s" => \$OutputLogPath{2},
243 "logging-mode=s" => \$LogMode,
244 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300245 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400246 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400247 "extra-info=s" => \$ExtraInfo,
248 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400249 "force!" => \$Force,
250 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400251 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400252 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400253 "quick!" => \$Quick,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400254 "all-affected!" => \$AllAffected,
255 "skip-internal=s" => \$SkipInternal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400256) or ERR_MESSAGE();
257
258sub ERR_MESSAGE()
259{
260 printMsg("INFO", "\n".$ShortUsage);
261 exit($ERROR_CODE{"Error"});
262}
263
264my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
265my $SLIB_TYPE = $LIB_TYPE;
266if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
267{ # show as "shared" library
268 $SLIB_TYPE = "shared";
269}
270my $LIB_EXT = getLIB_EXT($OSgroup);
271my $AR_EXT = getAR_EXT($OSgroup);
272my $BYTE_SIZE = 8;
273my $COMMON_LOG_PATH = "logs/run.log";
274
275my $HelpMessage="
276NAME:
277 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400278 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400279
280DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400281 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400282 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
283 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
284 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
285 and/or source-level compatibility: changes in calling stack, v-table changes,
286 removed symbols, renamed fields, etc. Binary incompatibility may result in
287 crashing or incorrect behavior of applications built with an old version of
288 a library if they run on a new one. Source incompatibility may result in
289 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400290
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400291 The tool is intended for developers of software libraries and maintainers
292 of operating systems who are interested in ensuring backward compatibility,
293 i.e. allow old applications to run or to be recompiled with newer library
294 versions.
295
296 Also the tool can be used by ISVs for checking applications portability to
297 new library versions. Found issues can be taken into account when adapting
298 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400299
300 This tool is free software: you can redistribute it and/or modify it
301 under the terms of the GNU LGPL or GNU GPL.
302
303USAGE:
304 $CmdName [options]
305
306EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400307 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400308
309 OLD.xml and NEW.xml are XML-descriptors:
310
311 <version>
312 1.0
313 </version>
314
315 <headers>
316 /path1/to/header(s)/
317 /path2/to/header(s)/
318 ...
319 </headers>
320
321 <libs>
322 /path1/to/library(ies)/
323 /path2/to/library(ies)/
324 ...
325 </libs>
326
327INFORMATION OPTIONS:
328 -h|-help
329 Print this help.
330
331 -i|-info
332 Print complete info.
333
334 -v|-version
335 Print version information.
336
337 -dumpversion
338 Print the tool version ($TOOL_VERSION) and don't do anything else.
339
340GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400341 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400342 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400343
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400344 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400345 Descriptor of 1st (old) library version.
346 It may be one of the following:
347
348 1. XML-descriptor (VERSION.xml file):
349
350 <version>
351 1.0
352 </version>
353
354 <headers>
355 /path1/to/header(s)/
356 /path2/to/header(s)/
357 ...
358 </headers>
359
360 <libs>
361 /path1/to/library(ies)/
362 /path2/to/library(ies)/
363 ...
364 </libs>
365
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300366 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400367
368 2. ABI dump generated by -dump option
369 3. Directory with headers and/or $SLIB_TYPE libraries
370 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400371
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300372 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400373 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400374
375 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400376 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400377
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400378 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400379 Descriptor of 2nd (new) library version.
380
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400381 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400382 Create library ABI dump for the input XML descriptor. You can
383 transfer it anywhere and pass instead of the descriptor. Also
384 it can be used for debugging the tool.
385
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300386 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400387
388sub HELP_MESSAGE() {
389 printMsg("INFO", $HelpMessage."
390MORE INFO:
391 $CmdName --info\n");
392}
393
394sub INFO_MESSAGE()
395{
396 printMsg("INFO", "$HelpMessage
397EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400398 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300399 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400400 for portability to the new library version.
401
402 -static-libs
403 Check static libraries instead of the shared ones. The <libs> section
404 of the XML-descriptor should point to static libraries location.
405
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400406 -cross-gcc|-gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400407 Path to the cross GCC compiler to use instead of the usual (host) GCC.
408
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400409 -cross-prefix|-gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400410 GCC toolchain prefix.
411
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400412 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400413 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400414 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400415
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400416 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400417 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200418 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400419
420 In general case you should specify it in the XML-descriptor:
421 <version>
422 VERSION
423 </version>
424
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400425 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400426 Specify 2nd library version outside the descriptor.
427
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400428 -vnum NUM
429 Specify the library version in the generated ABI dump. The <version> section
430 of the input XML descriptor will be overwritten in this case.
431
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400432 -s|-strict
433 Treat all compatibility warnings as problems. Add a number of \"Low\"
434 severity problems to the return value of the tool.
435
436 -headers-only
437 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
438 provide a low quality compatibility report with false positives and
439 without detecting of added/removed symbols.
440
441 Alternatively you can write \"none\" word to the <libs> section
442 in the XML-descriptor:
443 <libs>
444 none
445 </libs>
446
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400447 -show-retval
448 Show the symbol's return type in the report.
449
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400450 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300451 This option allows to specify a file with a list of symbols (mangled
452 names in C++) that should be checked. Other symbols will not be checked.
453
454 -types-list PATH
455 This option allows to specify a file with a list of types that should
456 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400457
458 -skip-symbols PATH
459 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400460
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400461 -headers-list PATH
462 The file with a list of headers, that should be checked/dumped.
463
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400464 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400465 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400466
467 -header NAME
468 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400469
470 -use-dumps
471 Make dumps for two versions of a library and compare dumps. This should
472 increase the performance of the tool and decrease the system memory usage.
473
474 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400475 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400476
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400477 -dump-system NAME -sysroot DIR
478 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400479 create XML descriptors and make ABI dumps for each library. The result
480 set of ABI dumps can be compared (--cmp-systems) with the other one
481 created for other version of operating system in order to check them for
482 compatibility. Do not forget to specify -cross-gcc option if your target
483 system requires some specific version of GCC compiler (different from
484 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400485 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400486
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400487 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400488 The same as the previous option but takes an XML descriptor of the target
489 system as input, where you should describe it:
490
491 /* Primary sections */
492
493 <name>
494 /* Name of the system */
495 </name>
496
497 <headers>
498 /* The list of paths to header files and/or
499 directories with header files, one per line */
500 </headers>
501
502 <libs>
503 /* The list of paths to shared libraries and/or
504 directories with shared libraries, one per line */
505 </libs>
506
507 /* Optional sections */
508
509 <search_headers>
510 /* List of directories to be searched
511 for header files to automatically
512 generate include paths, one per line */
513 </search_headers>
514
515 <search_libs>
516 /* List of directories to be searched
517 for shared libraries to resolve
518 dependencies, one per line */
519 </search_libs>
520
521 <tools>
522 /* List of directories with tools used
523 for analysis (GCC toolchain), one per line */
524 </tools>
525
526 <cross_prefix>
527 /* GCC toolchain prefix.
528 Examples:
529 arm-linux-gnueabi
530 arm-none-symbianelf */
531 </cross_prefix>
532
533 <gcc_options>
534 /* Additional GCC options, one per line */
535 </gcc_options>
536
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400537 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300538 This option should be used with -dump-system option to dump
539 ABI of operating systems and configure the dumping process.
540 You can find a sample in the package:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400541 modules/Targets/{unix, symbian, windows}
542
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400543 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400544 Compare two system ABI dumps. Create compatibility reports for each
545 library and the common HTML report including the summary of test
546 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400547 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400548
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400549 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400550 The file with a list of libraries, that should be dumped by
551 the -dump-system option or should be checked by the -cmp-systems option.
552
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400553 -ext|-extended
554 If your library A is supposed to be used by other library B and you
555 want to control the ABI of B, then you should enable this option. The
556 tool will check for changes in all data types, even if they are not
557 used by any function in the library A. Such data types are not part
558 of the A library ABI, but may be a part of the ABI of the B library.
559
560 The short scheme is:
561 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
562
563 -q|-quiet
564 Print all messages to the file instead of stdout and stderr.
565 Default path (can be changed by -log-path option):
566 $COMMON_LOG_PATH
567
568 -stdout
569 Print analysis results (compatibility reports and ABI dumps) to stdout
570 instead of creating a file. This would allow piping data to other programs.
571
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400572 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400573 Change format of compatibility report.
574 Formats:
575 htm - HTML format (default)
576 xml - XML format
577
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400578 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400579 Change format of ABI dump.
580 Formats:
581 perl - Data::Dumper format (default)
582 xml - XML format
583
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400584 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400585 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400586
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400587 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400588 Set library language (C or C++). You can use this option if the tool
589 cannot auto-detect a language. This option may be useful for checking
590 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400591
592 -arch ARCH
593 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
594 ect.). The option is useful if the tool cannot detect correct architecture
595 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400596
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400597 -binary|-bin|-abi
598 Show \"Binary\" compatibility problems only.
599 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400600 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400601
602 -source|-src|-api
603 Show \"Source\" compatibility problems only.
604 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400605 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400606
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400607 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400608 The maximum number of affected symbols listed under the description
609 of the changed type in the report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400610
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400611OTHER OPTIONS:
612 -test
613 Run internal tests. Create two binary incompatible versions of a sample
614 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300615 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400616
617 -test-dump
618 Test ability to create, read and compare ABI dumps.
619
620 -debug
621 Debugging mode. Print debug info on the screen. Save intermediate
622 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400623 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400624
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400625 Also consider using --dump option for debugging the tool.
626
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400627 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400628 If your header files are written in C language and can be compiled
629 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
630 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400631
632 -cpp-incompatible
633 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400634
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400635 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400636 Path to file with the function parameter names. It can be used
637 for improving report view if the library header files have no
638 parameter names. File format:
639
640 func1;param1;param2;param3 ...
641 func2;param1;param2;param3 ...
642 ...
643
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400644 -relpath PATH
645 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400646 for dumping the library ABI (see -dump option).
647
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400648 -relpath1 PATH
649 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400650
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400651 -relpath2 PATH
652 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400653
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400654 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400655 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400656 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400657 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400658
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400659 -sort
660 Enable sorting of data in ABI dumps.
661
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400662 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400663 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400664 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400665 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400666
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400667 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400668 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400669 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400670 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400671
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400672 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400673 Path to \"Source\" compatibility report.
674 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400675 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400676
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400677 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400678 Log path for all messages.
679 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400680 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400681
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400682 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400683 Log path for 1st version of a library.
684 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400685 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400686
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400687 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400688 Log path for 2nd version of a library.
689 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400691
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400692 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400693 Change logging mode.
694 Modes:
695 w - overwrite old logs (default)
696 a - append old logs
697 n - do not write any logs
698
699 -list-affected
700 Generate file with the list of incompatible
701 symbols beside the HTML compatibility report.
702 Use 'c++filt \@file' command from GNU binutils
703 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400704 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400705 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400706 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400707
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400708 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400709 The component name in the title and summary of the HTML report.
710 Default:
711 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300712
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300713 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400714 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400715 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400716
717 -extra-info DIR
718 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400719
720 -extra-dump
721 Create extended ABI dump containing all symbols
722 from the translation unit.
723
724 -force
725 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400726
727 -tolerance LEVEL
728 Apply a set of heuristics to successfully compile input
729 header files. You can enable several tolerance levels by
730 joining them into one string (e.g. 13, 124, etc.).
731 Levels:
732 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
733 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
734 3 - skip headers that iclude non-Linux headers
735 4 - skip headers included by others
736
737 -tolerant
738 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400739
740 -check
741 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400742
743 -quick
744 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400745
746 -skip-internal PATTERN
747 Do not check internal interfaces matched by the pattern.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400748
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400749REPORT:
750 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400751 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400752
753 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400754 logs/LIB_NAME/V1/log.txt
755 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400756
757EXIT CODES:
758 0 - Compatible. The tool has run without any errors.
759 non-zero - Incompatible or the tool has run with errors.
760
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400761MORE INFORMATION:
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300762 ".$HomePage."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400763}
764
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400765my %Operator_Indication = (
766 "not" => "~",
767 "assign" => "=",
768 "andassign" => "&=",
769 "orassign" => "|=",
770 "xorassign" => "^=",
771 "or" => "|",
772 "xor" => "^",
773 "addr" => "&",
774 "and" => "&",
775 "lnot" => "!",
776 "eq" => "==",
777 "ne" => "!=",
778 "lt" => "<",
779 "lshift" => "<<",
780 "lshiftassign" => "<<=",
781 "rshiftassign" => ">>=",
782 "call" => "()",
783 "mod" => "%",
784 "modassign" => "%=",
785 "subs" => "[]",
786 "land" => "&&",
787 "lor" => "||",
788 "rshift" => ">>",
789 "ref" => "->",
790 "le" => "<=",
791 "deref" => "*",
792 "mult" => "*",
793 "preinc" => "++",
794 "delete" => " delete",
795 "vecnew" => " new[]",
796 "vecdelete" => " delete[]",
797 "predec" => "--",
798 "postinc" => "++",
799 "postdec" => "--",
800 "plusassign" => "+=",
801 "plus" => "+",
802 "minus" => "-",
803 "minusassign" => "-=",
804 "gt" => ">",
805 "ge" => ">=",
806 "new" => " new",
807 "multassign" => "*=",
808 "divassign" => "/=",
809 "div" => "/",
810 "neg" => "-",
811 "pos" => "+",
812 "memref" => "->*",
813 "compound" => "," );
814
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400815my %UnknownOperator;
816
817my %NodeType= (
818 "array_type" => "Array",
819 "binfo" => "Other",
820 "boolean_type" => "Intrinsic",
821 "complex_type" => "Intrinsic",
822 "const_decl" => "Other",
823 "enumeral_type" => "Enum",
824 "field_decl" => "Other",
825 "function_decl" => "Other",
826 "function_type" => "FunctionType",
827 "identifier_node" => "Other",
828 "integer_cst" => "Other",
829 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400830 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400831 "method_type" => "MethodType",
832 "namespace_decl" => "Other",
833 "parm_decl" => "Other",
834 "pointer_type" => "Pointer",
835 "real_cst" => "Other",
836 "real_type" => "Intrinsic",
837 "record_type" => "Struct",
838 "reference_type" => "Ref",
839 "string_cst" => "Other",
840 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400841 "template_type_parm" => "TemplateParam",
842 "typename_type" => "TypeName",
843 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400844 "tree_list" => "Other",
845 "tree_vec" => "Other",
846 "type_decl" => "Other",
847 "union_type" => "Union",
848 "var_decl" => "Other",
849 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400850 "nop_expr" => "Other", #
851 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400852 "offset_type" => "Other" );
853
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400854my %CppKeywords_C = map {$_=>1} (
855 # C++ 2003 keywords
856 "public",
857 "protected",
858 "private",
859 "default",
860 "template",
861 "new",
862 #"asm",
863 "dynamic_cast",
864 "auto",
865 "try",
866 "namespace",
867 "typename",
868 "using",
869 "reinterpret_cast",
870 "friend",
871 "class",
872 "virtual",
873 "const_cast",
874 "mutable",
875 "static_cast",
876 "export",
877 # C++0x keywords
878 "noexcept",
879 "nullptr",
880 "constexpr",
881 "static_assert",
882 "explicit",
883 # cannot be used as a macro name
884 # as it is an operator in C++
885 "and",
886 #"and_eq",
887 "not",
888 #"not_eq",
889 "or"
890 #"or_eq",
891 #"bitand",
892 #"bitor",
893 #"xor",
894 #"xor_eq",
895 #"compl"
896);
897
898my %CppKeywords_F = map {$_=>1} (
899 "delete",
900 "catch",
901 "alignof",
902 "thread_local",
903 "decltype",
904 "typeid"
905);
906
907my %CppKeywords_O = map {$_=>1} (
908 "bool",
909 "register",
910 "inline",
911 "operator"
912);
913
914my %CppKeywords_A = map {$_=>1} (
915 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400916 "throw",
917 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400918);
919
920foreach (keys(%CppKeywords_C),
921keys(%CppKeywords_F),
922keys(%CppKeywords_O)) {
923 $CppKeywords_A{$_}=1;
924}
925
926# Header file extensions as described by gcc
927my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
928
929my %IntrinsicMangling = (
930 "void" => "v",
931 "bool" => "b",
932 "wchar_t" => "w",
933 "char" => "c",
934 "signed char" => "a",
935 "unsigned char" => "h",
936 "short" => "s",
937 "unsigned short" => "t",
938 "int" => "i",
939 "unsigned int" => "j",
940 "long" => "l",
941 "unsigned long" => "m",
942 "long long" => "x",
943 "__int64" => "x",
944 "unsigned long long" => "y",
945 "__int128" => "n",
946 "unsigned __int128" => "o",
947 "float" => "f",
948 "double" => "d",
949 "long double" => "e",
950 "__float80" => "e",
951 "__float128" => "g",
952 "..." => "z"
953);
954
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400955my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
956
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400957my %StdcxxMangling = (
958 "3std"=>"St",
959 "3std9allocator"=>"Sa",
960 "3std12basic_string"=>"Sb",
961 "3std12basic_stringIcE"=>"Ss",
962 "3std13basic_istreamIcE"=>"Si",
963 "3std13basic_ostreamIcE"=>"So",
964 "3std14basic_iostreamIcE"=>"Sd"
965);
966
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +0400967my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400968my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
969
970my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400971my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400972
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400973my %ConstantSuffix = (
974 "unsigned int"=>"u",
975 "long"=>"l",
976 "unsigned long"=>"ul",
977 "long long"=>"ll",
978 "unsigned long long"=>"ull"
979);
980
981my %ConstantSuffixR =
982reverse(%ConstantSuffix);
983
984my %OperatorMangling = (
985 "~" => "co",
986 "=" => "aS",
987 "|" => "or",
988 "^" => "eo",
989 "&" => "an",#ad (addr)
990 "==" => "eq",
991 "!" => "nt",
992 "!=" => "ne",
993 "<" => "lt",
994 "<=" => "le",
995 "<<" => "ls",
996 "<<=" => "lS",
997 ">" => "gt",
998 ">=" => "ge",
999 ">>" => "rs",
1000 ">>=" => "rS",
1001 "()" => "cl",
1002 "%" => "rm",
1003 "[]" => "ix",
1004 "&&" => "aa",
1005 "||" => "oo",
1006 "*" => "ml",#de (deref)
1007 "++" => "pp",#
1008 "--" => "mm",#
1009 "new" => "nw",
1010 "delete" => "dl",
1011 "new[]" => "na",
1012 "delete[]" => "da",
1013 "+=" => "pL",
1014 "+" => "pl",#ps (pos)
1015 "-" => "mi",#ng (neg)
1016 "-=" => "mI",
1017 "*=" => "mL",
1018 "/=" => "dV",
1019 "&=" => "aN",
1020 "|=" => "oR",
1021 "%=" => "rM",
1022 "^=" => "eO",
1023 "/" => "dv",
1024 "->*" => "pm",
1025 "->" => "pt",#rf (ref)
1026 "," => "cm",
1027 "?" => "qu",
1028 "." => "dt",
1029 "sizeof"=> "sz"#st
1030);
1031
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001032my %Intrinsic_Keywords = map {$_=>1} (
1033 "true",
1034 "false",
1035 "_Bool",
1036 "_Complex",
1037 "const",
1038 "int",
1039 "long",
1040 "void",
1041 "short",
1042 "float",
1043 "volatile",
1044 "restrict",
1045 "unsigned",
1046 "signed",
1047 "char",
1048 "double",
1049 "class",
1050 "struct",
1051 "union",
1052 "enum"
1053);
1054
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001055my %GlibcHeader = map {$_=>1} (
1056 "aliases.h",
1057 "argp.h",
1058 "argz.h",
1059 "assert.h",
1060 "cpio.h",
1061 "ctype.h",
1062 "dirent.h",
1063 "envz.h",
1064 "errno.h",
1065 "error.h",
1066 "execinfo.h",
1067 "fcntl.h",
1068 "fstab.h",
1069 "ftw.h",
1070 "glob.h",
1071 "grp.h",
1072 "iconv.h",
1073 "ifaddrs.h",
1074 "inttypes.h",
1075 "langinfo.h",
1076 "limits.h",
1077 "link.h",
1078 "locale.h",
1079 "malloc.h",
1080 "math.h",
1081 "mntent.h",
1082 "monetary.h",
1083 "nl_types.h",
1084 "obstack.h",
1085 "printf.h",
1086 "pwd.h",
1087 "regex.h",
1088 "sched.h",
1089 "search.h",
1090 "setjmp.h",
1091 "shadow.h",
1092 "signal.h",
1093 "spawn.h",
1094 "stdarg.h",
1095 "stdint.h",
1096 "stdio.h",
1097 "stdlib.h",
1098 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001099 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001100 "tar.h",
1101 "termios.h",
1102 "time.h",
1103 "ulimit.h",
1104 "unistd.h",
1105 "utime.h",
1106 "wchar.h",
1107 "wctype.h",
1108 "wordexp.h" );
1109
1110my %GlibcDir = map {$_=>1} (
1111 "arpa",
1112 "bits",
1113 "gnu",
1114 "netinet",
1115 "net",
1116 "nfs",
1117 "rpc",
1118 "sys",
1119 "linux" );
1120
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001121my %WinHeaders = map {$_=>1} (
1122 "dos.h",
1123 "process.h",
1124 "winsock.h",
1125 "config-win.h",
1126 "mem.h",
1127 "windows.h",
1128 "winsock2.h",
1129 "crtdbg.h",
1130 "ws2tcpip.h"
1131);
1132
1133my %ObsoleteHeaders = map {$_=>1} (
1134 "iostream.h",
1135 "fstream.h"
1136);
1137
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001138my %AlienHeaders = map {$_=>1} (
1139 # Solaris
1140 "thread.h",
1141 "sys/atomic.h",
1142 # HPUX
1143 "sys/stream.h",
1144 # Symbian
1145 "AknDoc.h",
1146 # Atari ST
1147 "ext.h",
1148 "tos.h",
1149 # MS-DOS
1150 "alloc.h",
1151 # Sparc
1152 "sys/atomic.h"
1153);
1154
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001155my %ConfHeaders = map {$_=>1} (
1156 "atomic",
1157 "conf.h",
1158 "config.h",
1159 "configure.h",
1160 "build.h",
1161 "setup.h"
1162);
1163
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001164my %LocalIncludes = map {$_=>1} (
1165 "/usr/local/include",
1166 "/usr/local" );
1167
1168my %OS_AddPath=(
1169# These paths are needed if the tool cannot detect them automatically
1170 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001171 "include"=>[
1172 "/Library",
1173 "/Developer/usr/include"
1174 ],
1175 "lib"=>[
1176 "/Library",
1177 "/Developer/usr/lib"
1178 ],
1179 "bin"=>[
1180 "/Developer/usr/bin"
1181 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001182 },
1183 "beos"=>{
1184 # Haiku has GCC 2.95.3 by default
1185 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001186 "include"=>[
1187 "/boot/common",
1188 "/boot/develop"
1189 ],
1190 "lib"=>[
1191 "/boot/common/lib",
1192 "/boot/system/lib",
1193 "/boot/apps"
1194 ],
1195 "bin"=>[
1196 "/boot/common/bin",
1197 "/boot/system/bin",
1198 "/boot/develop/abi"
1199 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001201);
1202
1203my %Slash_Type=(
1204 "default"=>"/",
1205 "windows"=>"\\"
1206);
1207
1208my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1209
1210# Global Variables
1211my %COMMON_LANGUAGE=(
1212 1 => "C",
1213 2 => "C" );
1214
1215my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001216my $MAX_CPPFILT_FILE_SIZE = 50000;
1217my $CPPFILT_SUPPORT_FILE;
1218
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001219my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1220
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001221my $STDCXX_TESTING = 0;
1222my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001223my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001224
1225my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001226
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001227my $TargetComponent;
1228
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001229my $CheckUndefined = 0;
1230
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001231# Set Target Component Name
1232if($TargetComponent_Opt) {
1233 $TargetComponent = lc($TargetComponent_Opt);
1234}
1235else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001236{ # default: library
1237 # other components: header, system, ...
1238 $TargetComponent = "library";
1239}
1240
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001241my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001242
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001243my $SystemRoot;
1244
1245my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001246my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001247my %LOG_PATH;
1248my %DEBUG_PATH;
1249my %Cache;
1250my %LibInfo;
1251my $COMPILE_ERRORS = 0;
1252my %CompilerOptions;
1253my %CheckedDyLib;
1254my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1255
1256# Constants (#defines)
1257my %Constants;
1258my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001259my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001260
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001261# Extra Info
1262my %SymbolHeader;
1263my %KnownLibs;
1264
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001265# Templates
1266my %TemplateInstance;
1267my %BasicTemplate;
1268my %TemplateArg;
1269my %TemplateDecl;
1270my %TemplateMap;
1271
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001272# Types
1273my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001274my %SkipTypes = (
1275 "1"=>{},
1276 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001277my %CheckedTypes;
1278my %TName_Tid;
1279my %EnumMembName_Id;
1280my %NestedNameSpaces = (
1281 "1"=>{},
1282 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001283my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001284my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001285my %ClassVTable;
1286my %ClassVTable_Content;
1287my %VTableClass;
1288my %AllocableClass;
1289my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001290my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001291my %Class_SubClasses;
1292my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001293my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001294my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001295
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001296my %CheckedTypeInfo;
1297
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001298# Typedefs
1299my %Typedef_BaseName;
1300my %Typedef_Tr;
1301my %Typedef_Eq;
1302my %StdCxxTypedef;
1303my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001304my %MissedBase;
1305my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001306my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001307
1308# Symbols
1309my %SymbolInfo;
1310my %tr_name;
1311my %mangled_name_gcc;
1312my %mangled_name;
1313my %SkipSymbols = (
1314 "1"=>{},
1315 "2"=>{} );
1316my %SkipNameSpaces = (
1317 "1"=>{},
1318 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001319my %AddNameSpaces = (
1320 "1"=>{},
1321 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001322my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001323my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001324my %SymbolsList_App;
1325my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001326my %Symbol_Library = (
1327 "1"=>{},
1328 "2"=>{} );
1329my %Library_Symbol = (
1330 "1"=>{},
1331 "2"=>{} );
1332my %DepSymbol_Library = (
1333 "1"=>{},
1334 "2"=>{} );
1335my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001336 "1"=>{},
1337 "2"=>{} );
1338my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001339my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001340my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001341my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001342my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001343my %Library_Needed= (
1344 "1"=>{},
1345 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001346
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001347# Extra Info
1348my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001349my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001350
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001351# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001352my %Include_Preamble = (
1353 "1"=>[],
1354 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001355my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001356my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001357my %HeaderName_Paths;
1358my %Header_Dependency;
1359my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001360my %Include_Paths = (
1361 "1"=>[],
1362 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001363my %INC_PATH_AUTODETECT = (
1364 "1"=>1,
1365 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001366my %Add_Include_Paths = (
1367 "1"=>[],
1368 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001369my %Skip_Include_Paths;
1370my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001371my %Header_ErrorRedirect;
1372my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001373my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001374my %Header_ShouldNotBeUsed;
1375my %RecursiveIncludes;
1376my %Header_Include_Prefix;
1377my %SkipHeaders;
1378my %SkipHeadersList=(
1379 "1"=>{},
1380 "2"=>{} );
1381my %SkipLibs;
1382my %Include_Order;
1383my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001384my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001385my %TUnit_Funcs;
1386my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001387
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001388my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001389 "1"=>0,
1390 "2"=>0 );
1391my %AutoPreambleMode = (
1392 "1"=>0,
1393 "2"=>0 );
1394my %MinGWMode = (
1395 "1"=>0,
1396 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001397my %Cpp0xMode = (
1398 "1"=>0,
1399 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001400
1401# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001402my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001403my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001404my %RegisteredSONAMEs;
1405my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001406
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001407my %CheckedArch;
1408
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001409# System Objects
1410my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001411my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001412my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001413
1414# System Headers
1415my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001416my @DefaultCppPaths;
1417my @DefaultGccPaths;
1418my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001419my %DefaultCppHeader;
1420my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001421my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001422
1423# Merging
1424my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001425my $Version;
1426my %AddedInt;
1427my %RemovedInt;
1428my %AddedInt_Virt;
1429my %RemovedInt_Virt;
1430my %VirtualReplacement;
1431my %ChangedTypedef;
1432my %CompatRules;
1433my %IncompleteRules;
1434my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001435my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001436my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001437my %ReturnedClass;
1438my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001439my %SourceAlternative;
1440my %SourceAlternative_B;
1441my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001442my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001443
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001444# Calling Conventions
1445my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001446 1=>{ "R"=>0, "P"=>0 },
1447 2=>{ "R"=>0, "P"=>0 }
1448);
1449
1450# ABI Dump
1451my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001452
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001453# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001454my %TargetLibs;
1455my %TargetHeaders;
1456
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001457# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001458my $OStarget = $OSgroup;
1459my %TargetTools;
1460
1461# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001462my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001463
1464# Recursion locks
1465my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001466my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001467my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001468my @RecurInclude;
1469my @RecurConstant;
1470
1471# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001472my %SystemPaths = (
1473 "include"=>[],
1474 "lib"=>[],
1475 "bin"=>[]
1476);
1477my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001478my $GCC_PATH;
1479
1480# Symbols versioning
1481my %SymVer = (
1482 "1"=>{},
1483 "2"=>{} );
1484
1485# Problem descriptions
1486my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001487my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001488my %TotalAffected;
1489
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001490# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001491my $ContentID = 1;
1492my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1493my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1494my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1495my $ContentSpanEnd = "</span>\n";
1496my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1497my $ContentDivEnd = "</div>\n";
1498my $Content_Counter = 0;
1499
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001500# Modes
1501my $JoinReport = 1;
1502my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001503
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001504my %Severity_Val=(
1505 "High"=>3,
1506 "Medium"=>2,
1507 "Low"=>1,
1508 "Safe"=>-1
1509);
1510
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001511sub get_Modules()
1512{
1513 my $TOOL_DIR = get_dirname($0);
1514 if(not $TOOL_DIR)
1515 { # patch for MS Windows
1516 $TOOL_DIR = ".";
1517 }
1518 my @SEARCH_DIRS = (
1519 # tool's directory
1520 abs_path($TOOL_DIR),
1521 # relative path to modules
1522 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001523 # install path
1524 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001525 );
1526 foreach my $DIR (@SEARCH_DIRS)
1527 {
1528 if(not is_abs($DIR))
1529 { # relative path
1530 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1531 }
1532 if(-d $DIR."/modules") {
1533 return $DIR."/modules";
1534 }
1535 }
1536 exitStatus("Module_Error", "can't find modules");
1537}
1538
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001539my %LoadedModules = ();
1540
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001541sub loadModule($)
1542{
1543 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001544 if(defined $LoadedModules{$Name}) {
1545 return;
1546 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001547 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1548 if(not -f $Path) {
1549 exitStatus("Module_Error", "can't access \'$Path\'");
1550 }
1551 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001552 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001553}
1554
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001555sub readModule($$)
1556{
1557 my ($Module, $Name) = @_;
1558 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1559 if(not -f $Path) {
1560 exitStatus("Module_Error", "can't access \'$Path\'");
1561 }
1562 return readFile($Path);
1563}
1564
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001565sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001566{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001567 my $Number = $_[0];
1568 if(not $Number) {
1569 $Number = 1;
1570 }
1571 else {
1572 $Number = int($Number)+1;
1573 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001574 if($Number>3) {
1575 return $Number."th";
1576 }
1577 elsif($Number==1) {
1578 return "1st";
1579 }
1580 elsif($Number==2) {
1581 return "2nd";
1582 }
1583 elsif($Number==3) {
1584 return "3rd";
1585 }
1586 else {
1587 return $Number;
1588 }
1589}
1590
1591sub search_Tools($)
1592{
1593 my $Name = $_[0];
1594 return "" if(not $Name);
1595 if(my @Paths = keys(%TargetTools))
1596 {
1597 foreach my $Path (@Paths)
1598 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001599 if(-f join_P($Path, $Name)) {
1600 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001601 }
1602 if($CrossPrefix)
1603 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001604 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001605 if(-f $Candidate) {
1606 return $Candidate;
1607 }
1608 }
1609 }
1610 }
1611 else {
1612 return "";
1613 }
1614}
1615
1616sub synch_Cmd($)
1617{
1618 my $Name = $_[0];
1619 if(not $GCC_PATH)
1620 { # GCC was not found yet
1621 return "";
1622 }
1623 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001624 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001625 return $Candidate;
1626 }
1627 return "";
1628}
1629
1630sub get_CmdPath($)
1631{
1632 my $Name = $_[0];
1633 return "" if(not $Name);
1634 if(defined $Cache{"get_CmdPath"}{$Name}) {
1635 return $Cache{"get_CmdPath"}{$Name};
1636 }
1637 my %BinUtils = map {$_=>1} (
1638 "c++filt",
1639 "objdump",
1640 "readelf"
1641 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001642 if($BinUtils{$Name} and $GCC_PATH)
1643 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001644 if(my $Dir = get_dirname($GCC_PATH)) {
1645 $TargetTools{$Dir}=1;
1646 }
1647 }
1648 my $Path = search_Tools($Name);
1649 if(not $Path and $OSgroup eq "windows") {
1650 $Path = search_Tools($Name.".exe");
1651 }
1652 if(not $Path and $BinUtils{$Name})
1653 {
1654 if($CrossPrefix)
1655 { # user-defined prefix
1656 $Path = search_Cmd($CrossPrefix."-".$Name);
1657 }
1658 }
1659 if(not $Path and $BinUtils{$Name})
1660 {
1661 if(my $Candidate = synch_Cmd($Name))
1662 { # synch with GCC
1663 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001664 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001665 if(-f $Candidate) {
1666 $Path = $Candidate;
1667 }
1668 }
1669 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001670 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001671 $Path = $Candidate;
1672 }
1673 }
1674 }
1675 if(not $Path) {
1676 $Path = search_Cmd($Name);
1677 }
1678 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001679 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001680 $Path=search_Cmd($Name.".exe");
1681 }
1682 if($Path=~/\s/) {
1683 $Path = "\"".$Path."\"";
1684 }
1685 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1686}
1687
1688sub search_Cmd($)
1689{
1690 my $Name = $_[0];
1691 return "" if(not $Name);
1692 if(defined $Cache{"search_Cmd"}{$Name}) {
1693 return $Cache{"search_Cmd"}{$Name};
1694 }
1695 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1696 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1697 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001698 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001699 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001700 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001701 if(-f $CmdPath)
1702 {
1703 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001704 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001705 }
1706 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1707 }
1708 }
1709 return ($Cache{"search_Cmd"}{$Name} = "");
1710}
1711
1712sub get_CmdPath_Default($)
1713{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001714 return "" if(not $_[0]);
1715 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1716 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001717 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001718 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1719}
1720
1721sub get_CmdPath_Default_I($)
1722{ # search in PATH
1723 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001724 if($Name=~/find/)
1725 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001726 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001727 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001728 }
1729 }
1730 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001731 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001732 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001733 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001734 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001735 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001736 if($OSgroup eq "windows")
1737 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001738 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001739 return $Name;
1740 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001741 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001742 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001743 {
1744 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001745 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001746 }
1747 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001748 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001749}
1750
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001751sub classifyPath($)
1752{
1753 my $Path = $_[0];
1754 if($Path=~/[\*\[]/)
1755 { # wildcard
1756 $Path=~s/\*/.*/g;
1757 $Path=~s/\\/\\\\/g;
1758 return ($Path, "Pattern");
1759 }
1760 elsif($Path=~/[\/\\]/)
1761 { # directory or relative path
1762 return (path_format($Path, $OSgroup), "Path");
1763 }
1764 else {
1765 return ($Path, "Name");
1766 }
1767}
1768
1769sub readDescriptor($$)
1770{
1771 my ($LibVersion, $Content) = @_;
1772 return if(not $LibVersion);
1773 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1774 if(not $Content) {
1775 exitStatus("Error", "$DName is empty");
1776 }
1777 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001778 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001779 }
1780 $Content=~s/\/\*(.|\n)+?\*\///g;
1781 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001782
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001783 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1784 if($TargetVersion{$LibVersion}) {
1785 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1786 }
1787 if(not $Descriptor{$LibVersion}{"Version"}) {
1788 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1789 }
1790 if($Content=~/{RELPATH}/)
1791 {
1792 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1793 $Content =~ s/{RELPATH}/$RelDir/g;
1794 }
1795 else
1796 {
1797 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1798 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1799 }
1800 }
1801
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001802 my $DHeaders = parseTag(\$Content, "headers");
1803 if(not $DHeaders) {
1804 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1805 }
1806 elsif(lc($DHeaders) ne "none")
1807 { # append the descriptor headers list
1808 if($Descriptor{$LibVersion}{"Headers"})
1809 { # multiple descriptors
1810 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001811 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001812 else {
1813 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1814 }
1815 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1816 {
1817 if(not -e $Path) {
1818 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001819 }
1820 }
1821 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001822
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001823 if(not $CheckHeadersOnly_Opt)
1824 {
1825 my $DObjects = parseTag(\$Content, "libs");
1826 if(not $DObjects) {
1827 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1828 }
1829 elsif(lc($DObjects) ne "none")
1830 { # append the descriptor libraries list
1831 if($Descriptor{$LibVersion}{"Libs"})
1832 { # multiple descriptors
1833 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1834 }
1835 else {
1836 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1837 }
1838 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1839 {
1840 if(not -e $Path) {
1841 exitStatus("Access_Error", "can't access \'$Path\'");
1842 }
1843 }
1844 }
1845 }
1846 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1847 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001848 if(not -d $Path) {
1849 exitStatus("Access_Error", "can't access directory \'$Path\'");
1850 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001851 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001852 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001853 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001854 }
1855 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1856 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001857 if(not -d $Path) {
1858 exitStatus("Access_Error", "can't access directory \'$Path\'");
1859 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001860 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001861 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001862 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001863 }
1864 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1865 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001866 if(not -d $Path) {
1867 exitStatus("Access_Error", "can't access directory \'$Path\'");
1868 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001869 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001870 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001871 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001872 $TargetTools{$Path}=1;
1873 }
1874 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1875 $CrossPrefix = $Prefix;
1876 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001877 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001878 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1879 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001880 if(not -d $Path) {
1881 exitStatus("Access_Error", "can't access directory \'$Path\'");
1882 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001883 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001884 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001885 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001886 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001887 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001888 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1889 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001890 if(not -d $Path) {
1891 exitStatus("Access_Error", "can't access directory \'$Path\'");
1892 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001893 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001894 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001895 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001896 }
1897 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001898 { # skip some auto-generated include paths
1899 if(not is_abs($Path))
1900 {
1901 if(my $P = abs_path($Path)) {
1902 $Path = $P;
1903 }
1904 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001905 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001906 }
1907 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001908 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001909 my ($CPath, $Type) = classifyPath($Path);
1910 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001911 }
1912 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001913 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1914 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001915 if($Option!~/\A\-(Wl|l|L)/)
1916 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001917 $CompilerOptions{$LibVersion} .= " ".$Option;
1918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001919 }
1920 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1921 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1922 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001923 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001924 my ($CPath, $Type) = classifyPath($Path);
1925 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001926 }
1927 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1928 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1929 {
1930 my ($CPath, $Type) = classifyPath($Path);
1931 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1932 }
1933 if(my $DDefines = parseTag(\$Content, "defines"))
1934 {
1935 if($Descriptor{$LibVersion}{"Defines"})
1936 { # multiple descriptors
1937 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1938 }
1939 else {
1940 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1941 }
1942 }
1943 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1944 {
1945 if($Order=~/\A(.+):(.+)\Z/) {
1946 $Include_Order{$LibVersion}{$1} = $2;
1947 }
1948 }
1949 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1950 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001951 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001952 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1953 }
1954 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
1955 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001956 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001957 $SkipSymbols{$LibVersion}{$Symbol} = 1;
1958 }
1959 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
1960 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
1961 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001962 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
1963 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
1964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001965 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
1966 $SkipConstants{$LibVersion}{$Constant} = 1;
1967 }
1968 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
1969 {
1970 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001971 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001972 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
1973 }
1974 else {
1975 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
1976 }
1977 }
1978}
1979
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001980sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001981{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001982 my $CodeRef = shift(@_);
1983 my $Tag = shift(@_);
1984 if(not $Tag or not $CodeRef) {
1985 return undef;
1986 }
1987 my $Sp = 0;
1988 if(@_) {
1989 $Sp = shift(@_);
1990 }
1991 my $Start = index(${$CodeRef}, "<$Tag>");
1992 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001993 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001994 my $End = index(${$CodeRef}, "</$Tag>");
1995 if($End!=-1)
1996 {
1997 my $TS = length($Tag)+3;
1998 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
1999 substr($Content, 0, $TS-1, ""); # cut start tag
2000 substr($Content, -$TS, $TS, ""); # cut end tag
2001 if(not $Sp)
2002 {
2003 $Content=~s/\A\s+//g;
2004 $Content=~s/\s+\Z//g;
2005 }
2006 if(substr($Content, 0, 1) ne "<") {
2007 $Content = xmlSpecChars_R($Content);
2008 }
2009 return $Content;
2010 }
2011 }
2012 return undef;
2013}
2014
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002015sub getInfo($)
2016{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002017 my $DumpPath = $_[0];
2018 return if(not $DumpPath or not -f $DumpPath);
2019
2020 readTUDump($DumpPath);
2021
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002022 # processing info
2023 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002024
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002025 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002026 setAnonTypedef_All();
2027 }
2028
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002029 getTypeInfo_All();
2030 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002031 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002032 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002033 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002034
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002035 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002036 %LibInfo = ();
2037 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002038 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002039 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002040 %TemplateDecl = ();
2041 %StdCxxTypedef = ();
2042 %MissedTypedef = ();
2043 %Typedef_Tr = ();
2044 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002045 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002046
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002047 # clean cache
2048 delete($Cache{"getTypeAttr"});
2049 delete($Cache{"getTypeDeclId"});
2050
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002051 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002052 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002053 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002054 }
2055 else
2056 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002057 if($BinaryOnly and not $ExtendedCheck)
2058 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002059 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002060 }
2061 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002062 remove_Unused($Version, "Extended");
2063 }
2064 }
2065
2066 if($CheckInfo)
2067 {
2068 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2069 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2070 }
2071
2072 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2073 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002074 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002075 }
2076
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002077 if($Debug) {
2078 # debugMangling($Version);
2079 }
2080}
2081
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002082sub readTUDump($)
2083{
2084 my $DumpPath = $_[0];
2085
2086 open(TU_DUMP, $DumpPath);
2087 local $/ = undef;
2088 my $Content = <TU_DUMP>;
2089 close(TU_DUMP);
2090
2091 unlink($DumpPath);
2092
2093 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002094 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002095
2096 # clean memory
2097 undef $Content;
2098
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002099 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002100
2101 foreach (0 .. $#Lines)
2102 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002103 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002104 { # get a number and attributes of a node
2105 next if(not $NodeType{$2});
2106 $LibInfo{$Version}{"info_type"}{$1}=$2;
2107 $LibInfo{$Version}{"info"}{$1}=$3;
2108 }
2109
2110 # clean memory
2111 delete($Lines[$_]);
2112 }
2113
2114 # clean memory
2115 undef @Lines;
2116}
2117
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002118sub simplifyConstants()
2119{
2120 foreach my $Constant (keys(%{$Constants{$Version}}))
2121 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002122 if(defined $Constants{$Version}{$Constant}{"Header"})
2123 {
2124 my $Value = $Constants{$Version}{$Constant}{"Value"};
2125 if(defined $EnumConstants{$Version}{$Value}) {
2126 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2127 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002128 }
2129 }
2130}
2131
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002132sub simplifyNames()
2133{
2134 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2135 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002136 if($Typedef_Eq{$Version}{$Base}) {
2137 next;
2138 }
2139 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2140 if($#Translations==0)
2141 {
2142 if(length($Translations[0])<=length($Base)) {
2143 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2144 }
2145 }
2146 else
2147 { # select most appropriate
2148 foreach my $Tr (@Translations)
2149 {
2150 if($Base=~/\A\Q$Tr\E/)
2151 {
2152 $Typedef_Eq{$Version}{$Base} = $Tr;
2153 last;
2154 }
2155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002156 }
2157 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002158 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002159 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002160 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002161 if(not $TypeName) {
2162 next;
2163 }
2164 next if(index($TypeName,"<")==-1);# template instances only
2165 if($TypeName=~/>(::\w+)+\Z/)
2166 { # skip unused types
2167 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002168 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002169 foreach my $Base (sort {length($b)<=>length($a)}
2170 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002171 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002172 next if(not $Base);
2173 next if(index($TypeName,$Base)==-1);
2174 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002175 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002176 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002177 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2178 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2179 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002180 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002181 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2182 {
2183 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2184 {
2185 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2186 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002187 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002188 }
2189 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002190 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002191 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002192 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002193 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002194 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2195 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002196 }
2197}
2198
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002199sub setAnonTypedef_All()
2200{
2201 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2202 {
2203 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2204 {
2205 if(isAnon(getNameByInfo($InfoId))) {
2206 $TypedefToAnon{getTypeId($InfoId)} = 1;
2207 }
2208 }
2209 }
2210}
2211
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002212sub setTemplateParams_All()
2213{
2214 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2215 {
2216 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2217 setTemplateParams($_);
2218 }
2219 }
2220}
2221
2222sub setTemplateParams($)
2223{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002224 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002225 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002226 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002227 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002228 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002229 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002230 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002231 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002232 setTemplateInstParams($_[0], $TmplInst_Id);
2233 }
2234 }
2235
2236 $BasicTemplate{$Version}{$Tid} = $_[0];
2237
2238 if(my $Prms = getTreeAttr_Prms($_[0]))
2239 {
2240 if(my $Valu = getTreeAttr_Valu($Prms))
2241 {
2242 my $Vector = getTreeVec($Valu);
2243 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2244 {
2245 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2246 {
2247 if(my $Name = getNameByInfo($Val))
2248 {
2249 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2250 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2251 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2252 }
2253 else {
2254 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2255 }
2256 }
2257 }
2258 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002260 }
2261 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002262 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002263 {
2264 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2265 {
2266 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002267 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002268 }
2269 }
2270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002271}
2272
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002273sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002274{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002275 my ($Tmpl, $Inst) = @_;
2276
2277 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002278 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002279 my ($Params_InfoId, $ElemId) = ();
2280 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2281 $Params_InfoId = $1;
2282 }
2283 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2284 $ElemId = $1;
2285 }
2286 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002287 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002288 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2289 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2290 {
2291 my ($PPos, $PTypeId) = ($1, $2);
2292 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2293 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002294 if($PType eq "template_type_parm") {
2295 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002296 }
2297 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002298 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2299 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002300 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002301 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002302 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002303 else
2304 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002305 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002306 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002307 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002308 }
2309 }
2310 }
2311}
2312
2313sub getTypeDeclId($)
2314{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002315 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002316 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002317 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2318 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2319 }
2320 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2321 {
2322 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2323 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2324 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002325 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002326 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002327 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002328}
2329
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002330sub getTypeInfo_All()
2331{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002332 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002333 { # support for GCC < 4.5
2334 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2335 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2336 # FIXME: check GCC versions
2337 addMissedTypes_Pre();
2338 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002339
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002340 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002341 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002342 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2343 if($IType=~/_type\Z/ and $IType ne "function_type"
2344 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002345 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002346 }
2347 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002348
2349 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002350 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002351 "Name" => "...",
2352 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002353 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002354 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002355 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002356
2357 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002358 { # support for GCC < 4.5
2359 addMissedTypes_Post();
2360 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002361
2362 if($ADD_TMPL_INSTANCES)
2363 {
2364 # templates
2365 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2366 {
2367 if(defined $TemplateMap{$Version}{$Tid}
2368 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2369 {
2370 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2371 {
2372 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2373 {
2374 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2375 {
2376 if(my %MAttr = getTypeAttr($MembTypeId))
2377 {
2378 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2379 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2380 }
2381 }
2382 }
2383 }
2384 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2385 {
2386 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2387 {
2388 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2389
2390 if($NBid ne $Bid)
2391 {
2392 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2393 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2394 }
2395 }
2396 }
2397 }
2398 }
2399 }
2400}
2401
2402sub createType($$)
2403{
2404 my ($Attr, $LibVersion) = @_;
2405 my $NewId = ++$MAX_ID;
2406
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002407 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002408 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002409 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002410
2411 return "$NewId";
2412}
2413
2414sub instType($$$)
2415{ # create template instances
2416 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002417
2418 if(not $TypeInfo{$LibVersion}{$Tid}) {
2419 return undef;
2420 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002421 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2422
2423 foreach my $Key (sort keys(%{$Map}))
2424 {
2425 if(my $Val = $Map->{$Key})
2426 {
2427 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2428
2429 if(defined $Attr->{"NameSpace"}) {
2430 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2431 }
2432 foreach (keys(%{$Attr->{"TParam"}})) {
2433 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2434 }
2435 }
2436 else
2437 { # remove absent
2438 # _Traits, etc.
2439 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002440 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002441 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2442 }
2443 foreach (keys(%{$Attr->{"TParam"}}))
2444 {
2445 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2446 delete($Attr->{"TParam"}{$_});
2447 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002448 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002449 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2450 }
2451 }
2452 }
2453 }
2454
2455 my $Tmpl = 0;
2456
2457 if(defined $Attr->{"TParam"})
2458 {
2459 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2460 {
2461 my $PName = $Attr->{"TParam"}{$_}{"name"};
2462
2463 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2464 {
2465 my %Base = get_BaseType($PTid, $LibVersion);
2466
2467 if($Base{"Type"} eq "TemplateParam"
2468 or defined $Base{"Template"})
2469 {
2470 $Tmpl = 1;
2471 last
2472 }
2473 }
2474 }
2475 }
2476
2477 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2478 return "$Id";
2479 }
2480 else
2481 {
2482 if(not $Tmpl) {
2483 delete($Attr->{"Template"});
2484 }
2485
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002486 my $New = createType($Attr, $LibVersion);
2487
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002488 my %EMap = ();
2489 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2490 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2491 }
2492 foreach (keys(%{$Map})) {
2493 $EMap{$_} = $Map->{$_};
2494 }
2495
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002496 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2497 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002498 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002499 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002500 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002501 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002502 {
2503 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2504
2505 if($NBid ne $Bid)
2506 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002507 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2508 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002509 }
2510 }
2511 }
2512
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002513 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002514 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002515 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2516 {
2517 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2518 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2519 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002520 }
2521 }
2522
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002523 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002524 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002525 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2526 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002527 }
2528 }
2529
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002530 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2531 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002532 }
2533
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002534 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002535 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002536}
2537
2538sub addMissedTypes_Pre()
2539{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002540 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002541 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2542 { # detecting missed typedefs
2543 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2544 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002545 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002546 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002547 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002548 if($TypeType eq "Unknown")
2549 { # template_type_parm
2550 next;
2551 }
2552 my $TypeDeclId = getTypeDeclId($TypeId);
2553 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2554 my $TypedefName = getNameByInfo($MissedTDid);
2555 next if(not $TypedefName);
2556 next if($TypedefName eq "__float80");
2557 next if(isAnon($TypedefName));
2558 if(not $TypeDeclId
2559 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002560 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002561 }
2562 }
2563 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002564 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002565 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002566 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002567 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002568 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002569 next;
2570 }
2571 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002572 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002573 if(not $TypedefName) {
2574 next;
2575 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002576 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002577 my %MissedInfo = ( # typedef info
2578 "Name" => $TypedefName,
2579 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002580 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002581 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002582 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002583 my ($H, $L) = getLocation($MissedTDid);
2584 $MissedInfo{"Header"} = $H;
2585 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002586 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002587 { # other types
2588 next;
2589 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002590 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002591 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002592 next;
2593 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002594 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002595 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002596 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002597 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002598 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002599 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002600 next;
2601 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002602 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002603 next;
2604 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002605 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002606 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002607 next;
2608 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002609 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002610 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002611 next;
2612 }
2613 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002614
2615 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2616
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002617 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002618 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002619 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002620 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002621 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002622
2623 # add missed & remove other
2624 $TypeInfo{$Version} = \%AddTypes;
2625 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002626}
2627
2628sub addMissedTypes_Post()
2629{
2630 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2631 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002632 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2633 {
2634 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2635 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2636 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2637 }
2638 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002639 }
2640}
2641
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002642sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002643{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002644 my $TypeId = $_[0];
2645 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2646 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002647 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002648 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002649 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002650}
2651
2652sub getArraySize($$)
2653{
2654 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002655 if(my $Size = getSize($TypeId))
2656 {
2657 my $Elems = $Size/$BYTE_SIZE;
2658 while($BaseName=~s/\s*\[(\d+)\]//) {
2659 $Elems/=$1;
2660 }
2661 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2662 {
2663 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2664 $Elems/=$BasicSize;
2665 }
2666 }
2667 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002668 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002669 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002670}
2671
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002672sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002673{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002674 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002675 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002676 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2677 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002678 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002679 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2680 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2681 if(not $NodeType)
2682 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002683 return ();
2684 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002685 if($NodeType eq "tree_vec")
2686 {
2687 if($Pos!=$#Positions)
2688 { # select last vector of parameters ( ns<P1>::type<P2> )
2689 next;
2690 }
2691 }
2692 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2693 foreach my $P (@Params)
2694 {
2695 if($P eq "") {
2696 return ();
2697 }
2698 elsif($P ne "\@skip\@") {
2699 @TmplParams = (@TmplParams, $P);
2700 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002701 }
2702 }
2703 return @TmplParams;
2704}
2705
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002706sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002707{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002708 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002709 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002710 if(defined $TypeInfo{$Version}{$TypeId}
2711 and $TypeInfo{$Version}{$TypeId}{"Name"})
2712 { # already created
2713 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002714 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002715 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2716 { # incomplete type
2717 return ();
2718 }
2719 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2720
2721 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002722 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002723
2724 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2725 {
2726 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2727 {
2728 if($Info=~/qual[ ]*:/)
2729 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002730 my $NewId = ++$MAX_ID;
2731
2732 $MissedBase{$Version}{$TypeId} = "$NewId";
2733 $MissedBase_R{$Version}{$NewId} = $TypeId;
2734 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2735 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002736 }
2737 }
2738 $TypeAttr{"Type"} = "Typedef";
2739 }
2740 else {
2741 $TypeAttr{"Type"} = getTypeType($TypeId);
2742 }
2743
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002744 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2745 {
2746 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2747 { # local code
2748 return ();
2749 }
2750 }
2751
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002752 if($TypeAttr{"Type"} eq "Unknown") {
2753 return ();
2754 }
2755 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2756 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002757 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002758 if(my $TName = $TypeAttr{"Name"})
2759 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002760 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002761 $TName_Tid{$Version}{$TName} = $TypeId;
2762 return %TypeAttr;
2763 }
2764 else {
2765 return ();
2766 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002767 }
2768 elsif($TypeAttr{"Type"} eq "Array")
2769 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002770 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2771 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002772 return ();
2773 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002774 if(my $Algn = getAlgn($TypeId)) {
2775 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2776 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002777 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002778 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002779 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002780 if(not $BTAttr{"Name"}) {
2781 return ();
2782 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002783 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002784 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002785 if(my $Size = getSize($TypeId)) {
2786 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2787 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002788 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002789 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2790 }
2791 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002792 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002793 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002794 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002795 else
2796 {
2797 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002798 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002799 $TypeAttr{"Name"} = $1."[]".$2;
2800 }
2801 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002802 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002804 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002805 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002806 if($BTAttr{"Header"}) {
2807 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002808 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002809 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002810 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2811 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002812 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002813 return ();
2814 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002815 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002816 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002817 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002818 if($TypeAttr{"Name"})
2819 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002820 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002821
2822 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2823 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002824 { # NOTE: register only one int: with built-in decl
2825 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2826 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2827 }
2828 }
2829 return %TypeAttr;
2830 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002831 else {
2832 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002833 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002834 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002835 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2836 {
2837 %TypeAttr = getTrivialTypeAttr($TypeId);
2838 if($TypeAttr{"Name"})
2839 {
2840 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2841 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2842 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2843 }
2844 return %TypeAttr;
2845 }
2846 else {
2847 return ();
2848 }
2849 }
2850 elsif($TypeAttr{"Type"} eq "SizeOf")
2851 {
2852 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2853 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2854 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2855 if($TypeAttr{"Name"})
2856 {
2857 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2858 return %TypeAttr;
2859 }
2860 else {
2861 return ();
2862 }
2863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002864 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002865 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002866 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2867 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002868 return ();
2869 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002870 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002871 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002872 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002873 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002874 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002875 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002876 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002877 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002878 }
2879 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002880 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002881 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002882 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002883 return ();
2884 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002885 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002886 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002887 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002888 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002889 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002890 }
2891 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002892 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002893 {
2894 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002895 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002896 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002897 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002898 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2899 }
2900 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002901 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002902 }
2903 }
2904 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002905 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002906 }
2907 if($TypeAttr{"Type"} eq "Typedef")
2908 {
2909 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002910
2911 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2912 return ();
2913 }
2914
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002915 if(isAnon($TypeAttr{"Name"}))
2916 { # anon typedef to anon type: ._N
2917 return ();
2918 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002919
2920 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2921 { # artificial typedef of "struct X" to "X"
2922 $TypeAttr{"Artificial"} = 1;
2923 }
2924
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002925 if(my $NS = getNameSpace($TypeDeclId))
2926 {
2927 my $TypeName = $TypeAttr{"Name"};
2928 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2929 { # "some_type" is the typedef to "struct some_type" in C++
2930 if($3) {
2931 $TypeAttr{"Name"} = $3."::".$TypeName;
2932 }
2933 }
2934 else
2935 {
2936 $TypeAttr{"NameSpace"} = $NS;
2937 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002938
2939 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2940 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2941 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002942 if($BTAttr{"NameSpace"}
2943 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002944 { # types like "std::fpos<__mbstate_t>" are
2945 # not covered by typedefs in the TU dump
2946 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002947 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2948 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002949 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002950 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002951 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002952 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002953 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002954 }
2955 }
2956 }
2957 }
2958 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002959 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002960 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002961 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002962 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2963 { # typedef int*const TYPEDEF; // first
2964 # int foo(TYPEDEF p); // const is optimized out
2965 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2966 if($BTAttr{"Name"}=~/</)
2967 {
2968 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2969 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2970 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002971 }
2972 }
2973 }
2974 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
2975 }
2976 if(not $TypeAttr{"Size"})
2977 {
2978 if($TypeAttr{"Type"} eq "Pointer") {
2979 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
2980 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002981 elsif($BTAttr{"Size"}) {
2982 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002983 }
2984 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002985 if(my $Algn = getAlgn($TypeId)) {
2986 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2987 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002988 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002989 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
2990 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002991 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002992 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002993 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002994 { # typedef to "class Class"
2995 # should not be registered in TName_Tid
2996 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2997 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2998 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002999 }
3000 return %TypeAttr;
3001 }
3002}
3003
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003004sub getTreeVec($)
3005{
3006 my %Vector = ();
3007 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3008 {
3009 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3010 { # string length is N-1 because of the null terminator
3011 $Vector{$1} = $2;
3012 }
3013 }
3014 return \%Vector;
3015}
3016
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003017sub get_TemplateParam($$)
3018{
3019 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003020 return () if(not $Type_Id);
3021 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3022 return () if(not $NodeType);
3023 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003024 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003025 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003026 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003027 my $Num = getNodeIntCst($Type_Id);
3028 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003029 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003030 }
3031 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003032 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003033 }
3034 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003035 elsif($NodeType eq "string_cst") {
3036 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003037 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003038 elsif($NodeType eq "tree_vec")
3039 {
3040 my $Vector = getTreeVec($Type_Id);
3041 my @Params = ();
3042 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3043 {
3044 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3045 push(@Params, $P2);
3046 }
3047 }
3048 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003049 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003050 elsif($NodeType eq "parm_decl")
3051 {
3052 (getNameByInfo($Type_Id));
3053 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003054 else
3055 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003056 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003057 my $PName = $ParamAttr{"Name"};
3058 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003059 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003060 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003061 if($PName=~/\>/)
3062 {
3063 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003064 $PName = $Cover;
3065 }
3066 }
3067 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003068 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003069 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3070 # template<typename _Key, typename _Compare = std::less<_Key>
3071 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3072 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3073 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3074 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003075 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003076 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003077 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003078 }
3079}
3080
3081sub cover_stdcxx_typedef($)
3082{
3083 my $TypeName = $_[0];
3084 if(my @Covers = sort {length($a)<=>length($b)}
3085 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3086 { # take the shortest typedef
3087 # FIXME: there may be more than
3088 # one typedefs to the same type
3089 return $Covers[0];
3090 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003091 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003092 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3093 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3094 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003095 if(my $Cover = $Covers[0])
3096 {
3097 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3098 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3099 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003100 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003101 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003102}
3103
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003104sub getNodeIntCst($)
3105{
3106 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003107 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003108 if($EnumMembName_Id{$Version}{$CstId}) {
3109 return $EnumMembName_Id{$Version}{$CstId};
3110 }
3111 elsif((my $Value = getTreeValue($CstId)) ne "")
3112 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003113 if($Value eq "0")
3114 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003115 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003116 return "false";
3117 }
3118 else {
3119 return "0";
3120 }
3121 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003122 elsif($Value eq "1")
3123 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003124 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003125 return "true";
3126 }
3127 else {
3128 return "1";
3129 }
3130 }
3131 else {
3132 return $Value;
3133 }
3134 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003135 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003136}
3137
3138sub getNodeStrCst($)
3139{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003140 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3141 {
3142 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003143 {
3144 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3145 { # string length is N-1 because of the null terminator
3146 return substr($1, 0, $2-1);
3147 }
3148 else
3149 { # identifier_node
3150 return substr($1, 0, $2);
3151 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003152 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003153 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003154 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003155}
3156
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003157sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003158{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003159 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003160 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3161 if($Type eq "FieldPtr") {
3162 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3163 }
3164 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3165 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003166 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003167 if($Type eq "MethodPtr")
3168 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003169 if(my $Size = getSize($TypeId))
3170 {
3171 $Size/=$BYTE_SIZE;
3172 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003173 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003174 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003175 if(my $Algn = getAlgn($TypeId)) {
3176 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3177 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003178 # Return
3179 if($Type eq "FieldPtr")
3180 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003181 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003182 if($ReturnAttr{"Name"}) {
3183 $MemPtrName .= $ReturnAttr{"Name"};
3184 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003185 $TypeAttr{"Return"} = $PtrId;
3186 }
3187 else
3188 {
3189 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3190 {
3191 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003192 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3193 if(not $ReturnAttr{"Name"})
3194 { # templates
3195 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003196 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003197 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003198 $TypeAttr{"Return"} = $ReturnTypeId;
3199 }
3200 }
3201 # Class
3202 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3203 {
3204 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003205 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003206 if($Class{"Name"}) {
3207 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3208 }
3209 else {
3210 $MemPtrName .= " (*)";
3211 }
3212 }
3213 else {
3214 $MemPtrName .= " (*)";
3215 }
3216 # Parameters
3217 if($Type eq "FuncPtr"
3218 or $Type eq "MethodPtr")
3219 {
3220 my @ParamTypeName = ();
3221 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3222 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003223 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003224 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003225 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003226 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003227 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3228 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003229 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003230 my $PTypeId = $1;
3231 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003232 if(not $ParamAttr{"Name"})
3233 { # templates (template_type_parm), etc.
3234 return ();
3235 }
3236 if($ParamAttr{"Name"} eq "void") {
3237 last;
3238 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003239 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003240 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003241 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003242 push(@ParamTypeName, $ParamAttr{"Name"});
3243 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003244 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3245 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003246 }
3247 else {
3248 last;
3249 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003250 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003251 else {
3252 last;
3253 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003254 }
3255 }
3256 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3257 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003258 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003259 return %TypeAttr;
3260}
3261
3262sub getTreeTypeName($)
3263{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003264 my $TypeId = $_[0];
3265 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003266 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003267 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003268 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003269 if(my $Name = getNameByInfo($TypeId))
3270 { # bit_size_type
3271 return $Name;
3272 }
3273 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003274 return "unsigned int";
3275 }
3276 else {
3277 return "int";
3278 }
3279 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003280 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003281 return getNameByInfo($1);
3282 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003283 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003284 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003285}
3286
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003287sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003288{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003289 my $Ptd = pointTo($_[0]);
3290 return 0 if(not $Ptd);
3291 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003292 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003293 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3294 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003295 }
3296 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003297 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3298 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003299 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003300 if($InfoT1 eq "pointer_type"
3301 and $InfoT2 eq "function_type") {
3302 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003303 }
3304 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003305 return 0;
3306}
3307
3308sub isMethodPtr($)
3309{
3310 my $Ptd = pointTo($_[0]);
3311 return 0 if(not $Ptd);
3312 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3313 {
3314 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3315 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3316 and $Info=~/ ptrmem /) {
3317 return 1;
3318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003319 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003320 return 0;
3321}
3322
3323sub isFieldPtr($)
3324{
3325 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3326 {
3327 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3328 and $Info=~/ ptrmem /) {
3329 return 1;
3330 }
3331 }
3332 return 0;
3333}
3334
3335sub pointTo($)
3336{
3337 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3338 {
3339 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3340 return $1;
3341 }
3342 }
3343 return "";
3344}
3345
3346sub getTypeTypeByTypeId($)
3347{
3348 my $TypeId = $_[0];
3349 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3350 {
3351 my $NType = $NodeType{$TType};
3352 if($NType eq "Intrinsic") {
3353 return $NType;
3354 }
3355 elsif(isFuncPtr($TypeId)) {
3356 return "FuncPtr";
3357 }
3358 elsif(isMethodPtr($TypeId)) {
3359 return "MethodPtr";
3360 }
3361 elsif(isFieldPtr($TypeId)) {
3362 return "FieldPtr";
3363 }
3364 elsif($NType ne "Other") {
3365 return $NType;
3366 }
3367 }
3368 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003369}
3370
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003371my %UnQual = (
3372 "r"=>"restrict",
3373 "v"=>"volatile",
3374 "c"=>"const",
3375 "cv"=>"const volatile"
3376);
3377
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003378sub getQual($)
3379{
3380 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003381 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3382 {
3383 my ($Qual, $To) = ();
3384 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3385 $Qual = $UnQual{$1};
3386 }
3387 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3388 $To = $1;
3389 }
3390 if($Qual and $To) {
3391 return ($Qual, $To);
3392 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003393 }
3394 return ();
3395}
3396
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003397sub getQualType($)
3398{
3399 if($_[0] eq "const volatile") {
3400 return "ConstVolatile";
3401 }
3402 return ucfirst($_[0]);
3403}
3404
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003405sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003406{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003407 my $TypeId = $_[0];
3408 my $TypeDeclId = getTypeDeclId($TypeId);
3409 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003410 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003411 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3412 return "Typedef";
3413 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003414 }
3415 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3416 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003417 if(($Qual or $To) and $TypeDeclId
3418 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003419 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003420 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003421 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003422 elsif(not $MissedBase_R{$Version}{$TypeId}
3423 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003424 return "Typedef";
3425 }
3426 elsif($Qual)
3427 { # qualified types
3428 return getQualType($Qual);
3429 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003430
3431 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3432 { # typedef struct { ... } name
3433 $TypeTypedef{$Version}{$TypeId} = $1;
3434 }
3435
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003436 my $TypeType = getTypeTypeByTypeId($TypeId);
3437 if($TypeType eq "Struct")
3438 {
3439 if($TypeDeclId
3440 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3441 return "Template";
3442 }
3443 }
3444 return $TypeType;
3445}
3446
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003447sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003448{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003449 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003450 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003451 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3452 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3453 return 0;
3454 }
3455 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3456 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003457 if(my $TDid = getTypeDeclId($_[0]))
3458 {
3459 if(getTypeId($TDid) eq $_[0]
3460 and getNameByInfo($TDid))
3461 {
3462 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3463 return $1;
3464 }
3465 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003466 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003467 }
3468 }
3469 return 0;
3470}
3471
3472sub selectBaseType($)
3473{
3474 my $TypeId = $_[0];
3475 if(defined $MissedTypedef{$Version}{$TypeId})
3476 { # add missed typedefs
3477 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3478 return ($TypeId, "");
3479 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003480 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003481 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3482 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003483
3484 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3485 my $MB = $MissedBase{$Version}{$TypeId};
3486
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003487 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003488 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003489 and (getTypeId($1) ne $TypeId)
3490 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003491 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003492 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003493 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003494 elsif($MB)
3495 { # add base
3496 return ($MB, "");
3497 }
3498 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003499 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003500 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003501 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003502 elsif($Qual or $To)
3503 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003504 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003505 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003506 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003507 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003508 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003509 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003510 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003511 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003512 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003513 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003514 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003515 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003516 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003517 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003518 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003519 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003520 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003521 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003522 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003523 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003524
3525 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003526}
3527
3528sub getSymbolInfo_All()
3529{
3530 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3531 { # reverse order
3532 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003533 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003534 }
3535 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003536
3537 if($ADD_TMPL_INSTANCES)
3538 {
3539 # templates
3540 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3541 {
3542 my %Map = ();
3543
3544 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3545 {
3546 if(defined $TemplateMap{$Version}{$ClassId})
3547 {
3548 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3549 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3550 }
3551 }
3552 }
3553
3554 if(defined $TemplateMap{$Version}{$Sid})
3555 {
3556 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3557 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3558 }
3559 }
3560
3561 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3562 {
3563 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3564 {
3565 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3566 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3567 }
3568 }
3569 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3570 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3571 }
3572 }
3573 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003574}
3575
3576sub getVarInfo_All()
3577{
3578 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3579 { # reverse order
3580 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003581 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003582 }
3583 }
3584}
3585
3586sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003587 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003588}
3589
3590sub getVarInfo($)
3591{
3592 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003593 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003594 {
3595 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3596 if($NSInfoType and $NSInfoType eq "function_decl") {
3597 return;
3598 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003599 }
3600 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3601 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3602 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3603 delete($SymbolInfo{$Version}{$InfoId});
3604 return;
3605 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003606 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003607 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003608 delete($SymbolInfo{$Version}{$InfoId});
3609 return;
3610 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003611 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3612 delete($SymbolInfo{$Version}{$InfoId});
3613 return;
3614 }
3615 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003616 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3617 {
3618 if($OSgroup eq "windows")
3619 { # cut the offset
3620 $MnglName=~s/\@\d+\Z//g;
3621 }
3622 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3623 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003624 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003625 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003626 { # validate mangled name
3627 delete($SymbolInfo{$Version}{$InfoId});
3628 return;
3629 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003630 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003631 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003632 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003633 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003634 }
3635 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3636 { # non-public global data
3637 delete($SymbolInfo{$Version}{$InfoId});
3638 return;
3639 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003640 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003641 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003642 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003643 if(not defined $TypeInfo{$Version}{$Rid}
3644 or not $TypeInfo{$Version}{$Rid}{"Name"})
3645 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003646 delete($SymbolInfo{$Version}{$InfoId});
3647 return;
3648 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003649 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3650 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003651 if(defined $Val) {
3652 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003654 }
3655 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003656 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3657 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003658 if(not defined $TypeInfo{$Version}{$ClassId}
3659 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3660 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003661 delete($SymbolInfo{$Version}{$InfoId});
3662 return;
3663 }
3664 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003665 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3666 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003667 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003668 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003669 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003670 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003671 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003672 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003673 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003674 if(not $CheckHeadersOnly)
3675 {
3676 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3677 {
3678 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3679 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3680 {
3681 if(link_symbol($ShortName, $Version, "-Deps"))
3682 { # "const" global data is mangled as _ZL... in the TU dump
3683 # but not mangled when compiling a C shared library
3684 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3685 }
3686 }
3687 }
3688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003689 if($COMMON_LANGUAGE{$Version} eq "C++")
3690 {
3691 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3692 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003693 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003694 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3695 }
3696 }
3697 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3698 { # try to mangle symbol (link with libraries)
3699 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3700 }
3701 if($OStarget eq "windows")
3702 {
3703 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3704 { # link MS C++ symbols from library with GCC symbols from headers
3705 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3706 }
3707 }
3708 }
3709 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3710 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3711 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003712 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3713 {
3714 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3715 { # non-target symbols
3716 delete($SymbolInfo{$Version}{$InfoId});
3717 return;
3718 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003719 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003720 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3721 {
3722 if(defined $MissedTypedef{$Version}{$Rid})
3723 {
3724 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3725 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3726 }
3727 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003728 }
3729 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003730 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003731 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3732 }
3733 if($ShortName=~/\A(_Z|\?)/) {
3734 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3735 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003736
3737 if($ExtraDump) {
3738 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3739 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003740}
3741
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003742sub isConstType($$)
3743{
3744 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003745 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003746 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003747 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003748 }
3749 return ($Base{"Type"} eq "Const");
3750}
3751
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003752sub getTrivialName($$)
3753{
3754 my ($TypeInfoId, $TypeId) = @_;
3755 my %TypeAttr = ();
3756 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3757 if(not $TypeAttr{"Name"}) {
3758 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3759 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003760 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003761 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003762 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003763 if(isAnon($TypeAttr{"Name"}))
3764 {
3765 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003766 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003767 { # searching for a first not anon scope
3768 if($NSId eq $NameSpaceId) {
3769 last;
3770 }
3771 else
3772 {
3773 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3774 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003775 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003776 last;
3777 }
3778 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003779 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003780 }
3781 }
3782 else
3783 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003784 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003785 {
3786 if($NameSpaceId ne $TypeId) {
3787 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3788 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003789 }
3790 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003791 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003792 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3793 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003794 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003795 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003796 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003797 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003798 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003799 if($TypeAttr{"NameSpace"}) {
3800 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3801 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003802 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003803 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3804 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003805 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003806 if(my @TParams = getTParams($TypeId, "Type")) {
3807 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3808 }
3809 else {
3810 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3811 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003812 }
3813 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3814}
3815
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003816sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003817{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003818 my $TypeId = $_[0];
3819 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003820
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003821 my %TypeAttr = ();
3822
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003823 if($TemplateDecl{$Version}{$TypeId})
3824 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003825 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003826 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003827
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003828 setTypeAccess($TypeId, \%TypeAttr);
3829 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3830 if(isBuiltIn($TypeAttr{"Header"}))
3831 {
3832 delete($TypeAttr{"Header"});
3833 delete($TypeAttr{"Line"});
3834 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003835
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003836 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003837 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3838 if(not $TypeAttr{"Name"}) {
3839 return ();
3840 }
3841 if(not $TypeAttr{"NameSpace"}) {
3842 delete($TypeAttr{"NameSpace"});
3843 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003844
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003845 if($TypeAttr{"Type"} eq "Intrinsic")
3846 {
3847 if(defined $TypeAttr{"Header"})
3848 {
3849 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3850 { # support for SUSE 11.2
3851 # integer_type has srcp dump{1-2}.i
3852 delete($TypeAttr{"Header"});
3853 }
3854 }
3855 }
3856
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003857 my $Tmpl = undef;
3858
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003859 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003860 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003861 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3862
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003863 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003864 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003865 foreach my $Pos (0 .. $#TParams)
3866 {
3867 my $Val = $TParams[$Pos];
3868 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3869
3870 if(not defined $TypeAttr{"Template"})
3871 {
3872 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3873
3874 if($Base{"Type"} eq "TemplateParam"
3875 or defined $Base{"Template"}) {
3876 $TypeAttr{"Template"} = 1;
3877 }
3878 }
3879
3880 if($Tmpl)
3881 {
3882 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3883 {
3884 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3885
3886 if($Val eq $Arg) {
3887 $TypeAttr{"Template"} = 1;
3888 }
3889 }
3890 }
3891 }
3892
3893 if($Tmpl)
3894 {
3895 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3896 {
3897 if($Pos>$#TParams)
3898 {
3899 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3900 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3901 }
3902 }
3903 }
3904 }
3905
3906 if($ADD_TMPL_INSTANCES)
3907 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003908 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003909 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003910 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003911 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003912 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003913 {
3914 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3915 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3916 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003917 }
3918 if(not getTreeAttr_Binf($TypeId))
3919 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003920 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3921 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3922 }
3923 }
3924 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003925 }
3926 }
3927 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003928
3929 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3930
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003931 if(my $Size = getSize($TypeId))
3932 {
3933 $Size = $Size/$BYTE_SIZE;
3934 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003935 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003936 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003937 {
3938 if($ExtraDump)
3939 {
3940 if(not defined $TypeAttr{"Memb"}
3941 and not $Tmpl)
3942 { # declaration only
3943 $TypeAttr{"Forward"} = 1;
3944 }
3945 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003946 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003947
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003948 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003949 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003950 {
3951 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003952 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003953 }
3954 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003955 or $TypeAttr{"Type"} eq "Class")
3956 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003957 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003958 if($Skip) {
3959 return ();
3960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003961 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003962 if(my $Algn = getAlgn($TypeId)) {
3963 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003965 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003966
3967 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3968 {
3969 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003970 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003971 {
3972 if(not isAnon($TypeAttr{"Name"})) {
3973 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
3974 }
3975 }
3976 }
3977
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003978 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003979 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
3980 {
3981 my @Entries = split(/\n/, $VTable);
3982 foreach (1 .. $#Entries)
3983 {
3984 my $Entry = $Entries[$_];
3985 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003986 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003987 }
3988 }
3989 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003990
3991 if($TypeAttr{"Type"} eq "Enum")
3992 {
3993 if(not $TypeAttr{"NameSpace"})
3994 {
3995 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
3996 {
3997 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003998 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003999 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004000 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004001 "Header"=>$TypeAttr{"Header"}
4002 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004003 if(isAnon($TypeAttr{"Name"}))
4004 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004005 if($ExtraDump
4006 or is_target_header($TypeAttr{"Header"}, $Version))
4007 {
4008 %{$Constants{$Version}{$MName}} = (
4009 "Value" => $MVal,
4010 "Header" => $TypeAttr{"Header"}
4011 );
4012 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004013 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004014 }
4015 }
4016 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004017 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004018 {
4019 if(defined $TypedefToAnon{$TypeId}) {
4020 $TypeAttr{"AnonTypedef"} = 1;
4021 }
4022 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004023
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004024 return %TypeAttr;
4025}
4026
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004027sub simplifyVTable($)
4028{
4029 my $Content = $_[0];
4030 if($Content=~s/ \[with (.+)]//)
4031 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4032 if(my @Elems = separate_Params($1, 0, 0))
4033 {
4034 foreach my $Elem (@Elems)
4035 {
4036 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4037 {
4038 my ($Arg, $Val) = ($1, $2);
4039
4040 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4041 $Content=~s/,\s*$Arg\b//g;
4042 }
4043 else {
4044 $Content=~s/\b$Arg\b/$Val/g;
4045 }
4046 }
4047 }
4048 }
4049 }
4050
4051 return $Content;
4052}
4053
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004054sub detect_lang($)
4055{
4056 my $TypeId = $_[0];
4057 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004058 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004059 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004060 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4061 }
4062 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004063 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004064 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004065 while($Fncs)
4066 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004067 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004068 return 1;
4069 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004070 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004071 }
4072 }
4073 return 0;
4074}
4075
4076sub setSpec($$)
4077{
4078 my ($TypeId, $TypeAttr) = @_;
4079 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4080 if($Info=~/\s+spec\s+/) {
4081 $TypeAttr->{"Spec"} = 1;
4082 }
4083}
4084
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004085sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004086{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004087 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004088 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004089 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004090 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004091 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004092 my $Pos = 0;
4093 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4094 {
4095 my ($Access, $BInfoId) = ($1, $2);
4096 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004097
4098 if($ClassId==$TypeId)
4099 { # class A<N>:public A<N-1>
4100 next;
4101 }
4102
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004103 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4104 if(not $CType or $CType eq "template_type_parm"
4105 or $CType eq "typename_type")
4106 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004107 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004108 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004109 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004110 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004111 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4112 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004113 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004114 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4115 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004116 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004117 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004118 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004119 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4120 }
4121 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004122 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004123 }
4124 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004125 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004126}
4127
4128sub getBinfClassId($)
4129{
4130 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4131 $Info=~/type[ ]*:[ ]*@(\d+) /;
4132 return $1;
4133}
4134
4135sub unmangledFormat($$)
4136{
4137 my ($Name, $LibVersion) = @_;
4138 $Name = uncover_typedefs($Name, $LibVersion);
4139 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4140 $Name=~s/\(\w+\)(\d)/$1/;
4141 return $Name;
4142}
4143
4144sub modelUnmangled($$)
4145{
4146 my ($InfoId, $Compiler) = @_;
4147 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4148 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4149 }
4150 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4151 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4152 $PureSignature = "~".$PureSignature;
4153 }
4154 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4155 {
4156 my (@Params, @ParamTypes) = ();
4157 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4158 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4159 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4160 }
4161 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4162 { # checking parameters
4163 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004164 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004165 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004166 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004167
4168 if($PName eq "this"
4169 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4170 {
4171 next;
4172 }
4173
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004174 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004175 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004176 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004177 }
4178 @ParamTypes = (@ParamTypes, $PTName);
4179 }
4180 if(@ParamTypes) {
4181 $PureSignature .= "(".join(", ", @ParamTypes).")";
4182 }
4183 else
4184 {
4185 if($Compiler eq "MSVC")
4186 {
4187 $PureSignature .= "(void)";
4188 }
4189 else
4190 { # GCC
4191 $PureSignature .= "()";
4192 }
4193 }
4194 $PureSignature = delete_keywords($PureSignature);
4195 }
4196 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4197 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004198 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004199 $PureSignature = $ClassName."::".$PureSignature;
4200 }
4201 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4202 $PureSignature = $NS."::".$PureSignature;
4203 }
4204 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4205 $PureSignature .= " const";
4206 }
4207 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4208 $PureSignature .= " volatile";
4209 }
4210 my $ShowReturn = 0;
4211 if($Compiler eq "MSVC"
4212 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4213 {
4214 $ShowReturn=1;
4215 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004216 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4217 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004218 {
4219 $ShowReturn=1;
4220 }
4221 if($ShowReturn)
4222 { # mangled names for template function specializations include return value
4223 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4224 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004225 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004226 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4227 $PureSignature = $ReturnName." ".$PureSignature;
4228 }
4229 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004230 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004231}
4232
4233sub mangle_symbol($$$)
4234{ # mangling for simple methods
4235 # see gcc-4.6.0/gcc/cp/mangle.c
4236 my ($InfoId, $LibVersion, $Compiler) = @_;
4237 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4238 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4239 }
4240 my $Mangled = "";
4241 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004242 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004243 }
4244 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004245 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004246 }
4247 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4248}
4249
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004250sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004251{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004252 my ($InfoId, $LibVersion) = @_;
4253 return "";
4254}
4255
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004256sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004257{ # see gcc-4.6.0/gcc/cp/mangle.c
4258 my ($InfoId, $LibVersion) = @_;
4259 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004260 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004261 my %Repl = ();# SN_ replacements
4262 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4263 {
4264 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4265 if($MangledClass!~/\AN/) {
4266 $MangledClass = "N".$MangledClass;
4267 }
4268 else {
4269 $MangledClass=~s/E\Z//;
4270 }
4271 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4272 $MangledClass=~s/\AN/NV/;
4273 }
4274 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4275 $MangledClass=~s/\AN/NK/;
4276 }
4277 $Mangled .= $MangledClass;
4278 }
4279 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4280 { # mangled by name due to the absence of structured info
4281 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4282 if($MangledNS!~/\AN/) {
4283 $MangledNS = "N".$MangledNS;
4284 }
4285 else {
4286 $MangledNS=~s/E\Z//;
4287 }
4288 $Mangled .= $MangledNS;
4289 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004290 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004291 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004292 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004293 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004294 foreach (@TPos) {
4295 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4296 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004297 }
4298 elsif($TmplParams)
4299 { # remangling mode
4300 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004301 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004302 }
4303 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4304 $Mangled .= "C1";
4305 }
4306 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4307 $Mangled .= "D0";
4308 }
4309 elsif($ShortName)
4310 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004311 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4312 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004313 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004314 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004315 { # "const" global data is mangled as _ZL...
4316 $Mangled .= "L";
4317 }
4318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004319 if($ShortName=~/\Aoperator(\W.*)\Z/)
4320 {
4321 my $Op = $1;
4322 $Op=~s/\A[ ]+//g;
4323 if(my $OpMngl = $OperatorMangling{$Op}) {
4324 $Mangled .= $OpMngl;
4325 }
4326 else { # conversion operator
4327 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4328 }
4329 }
4330 else {
4331 $Mangled .= length($ShortName).$ShortName;
4332 }
4333 if(@TParams)
4334 { # templates
4335 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004336 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004337 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4338 }
4339 $Mangled .= "E";
4340 }
4341 if(not $ClassId and @TParams) {
4342 add_substitution($ShortName, \%Repl, 0);
4343 }
4344 }
4345 if($ClassId or $NameSpace) {
4346 $Mangled .= "E";
4347 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004348 if(@TParams)
4349 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004350 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004351 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4352 }
4353 }
4354 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4355 {
4356 my @Params = ();
4357 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4358 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4359 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4360 }
4361 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4362 { # checking parameters
4363 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4364 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4365 }
4366 if(not @Params) {
4367 $Mangled .= "v";
4368 }
4369 }
4370 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4371 $Mangled = write_stdcxx_substitution($Mangled);
4372 if($Mangled eq "_Z") {
4373 return "";
4374 }
4375 return $Mangled;
4376}
4377
4378sub correct_incharge($$$)
4379{
4380 my ($InfoId, $LibVersion, $Mangled) = @_;
4381 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4382 {
4383 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004384 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004385 }
4386 }
4387 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4388 {
4389 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004390 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004391 }
4392 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004393 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004394 }
4395 }
4396 return $Mangled;
4397}
4398
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004399sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004400{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004401 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004402 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004403 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004404 return $Name;
4405 }
4406 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004407 while(my $CPos = find_center($TParams, "<"))
4408 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004409 $TParams = substr($TParams, $CPos);
4410 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004411 if($TParams=~s/\A<(.+)>\Z/$1/) {
4412 $Name=~s/<\Q$TParams\E>\Z//;
4413 }
4414 else
4415 { # error
4416 $TParams = "";
4417 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004418 return ($Name, $TParams);
4419}
4420
4421sub get_sub_ns($)
4422{
4423 my $Name = $_[0];
4424 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004425 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004426 {
4427 push(@NS, substr($Name, 0, $CPos));
4428 $Name = substr($Name, $CPos);
4429 $Name=~s/\A:://;
4430 }
4431 return (join("::", @NS), $Name);
4432}
4433
4434sub mangle_ns($$$)
4435{
4436 my ($Name, $LibVersion, $Repl) = @_;
4437 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4438 {
4439 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4440 $Mangled=~s/\AN(.+)E\Z/$1/;
4441 return $Mangled;
4442
4443 }
4444 else
4445 {
4446 my ($MangledNS, $SubNS) = ("", "");
4447 ($SubNS, $Name) = get_sub_ns($Name);
4448 if($SubNS) {
4449 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4450 }
4451 $MangledNS .= length($Name).$Name;
4452 add_substitution($MangledNS, $Repl, 0);
4453 return $MangledNS;
4454 }
4455}
4456
4457sub mangle_param($$$)
4458{
4459 my ($PTid, $LibVersion, $Repl) = @_;
4460 my ($MPrefix, $Mangled) = ("", "");
4461 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004462 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004463 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004464 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004465 if(not $BaseType_Name) {
4466 return "";
4467 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004468 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004469 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004470 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4471 while($Suffix=~/(&|\*|const)\Z/)
4472 {
4473 if($Suffix=~s/[ ]*&\Z//) {
4474 $MPrefix .= "R";
4475 }
4476 if($Suffix=~s/[ ]*\*\Z//) {
4477 $MPrefix .= "P";
4478 }
4479 if($Suffix=~s/[ ]*const\Z//)
4480 {
4481 if($MPrefix=~/R|P/
4482 or $Suffix=~/&|\*/) {
4483 $MPrefix .= "K";
4484 }
4485 }
4486 if($Suffix=~s/[ ]*volatile\Z//) {
4487 $MPrefix .= "V";
4488 }
4489 #if($Suffix=~s/[ ]*restrict\Z//) {
4490 #$MPrefix .= "r";
4491 #}
4492 }
4493 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4494 $Mangled .= $Token;
4495 }
4496 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4497 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004498 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004499 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004500 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004501 foreach (@TPos) {
4502 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4503 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004504 }
4505 elsif($TmplParams)
4506 { # remangling mode
4507 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004508 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004509 }
4510 my $MangledNS = "";
4511 my ($SubNS, $SName) = get_sub_ns($ShortName);
4512 if($SubNS) {
4513 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4514 }
4515 $MangledNS .= length($SName).$SName;
4516 if(@TParams) {
4517 add_substitution($MangledNS, $Repl, 0);
4518 }
4519 $Mangled .= "N".$MangledNS;
4520 if(@TParams)
4521 { # templates
4522 $Mangled .= "I";
4523 foreach my $TParam (@TParams) {
4524 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4525 }
4526 $Mangled .= "E";
4527 }
4528 $Mangled .= "E";
4529 }
4530 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4531 {
4532 if($BaseType{"Type"} eq "MethodPtr") {
4533 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4534 }
4535 else {
4536 $Mangled .= "PF";
4537 }
4538 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4539 my @Params = keys(%{$BaseType{"Param"}});
4540 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4541 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4542 }
4543 if(not @Params) {
4544 $Mangled .= "v";
4545 }
4546 $Mangled .= "E";
4547 }
4548 elsif($BaseType{"Type"} eq "FieldPtr")
4549 {
4550 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4551 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4552 }
4553 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4554 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4555 {
4556 if($Mangled eq $Optimized)
4557 {
4558 if($ShortName!~/::/)
4559 { # remove "N ... E"
4560 if($MPrefix) {
4561 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4562 }
4563 else {
4564 $Mangled=~s/\AN(.+)E\Z/$1/g;
4565 }
4566 }
4567 }
4568 else {
4569 $Mangled = $Optimized;
4570 }
4571 }
4572 add_substitution($Mangled, $Repl, 1);
4573 return $Mangled;
4574}
4575
4576sub mangle_template_param($$$)
4577{ # types + literals
4578 my ($TParam, $LibVersion, $Repl) = @_;
4579 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4580 return mangle_param($TPTid, $LibVersion, $Repl);
4581 }
4582 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4583 { # class_name<1u>::method(...)
4584 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4585 }
4586 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4587 { # class_name<(signed char)1>::method(...)
4588 return "L".$IntrinsicMangling{$1}.$2."E";
4589 }
4590 elsif($TParam eq "true")
4591 { # class_name<true>::method(...)
4592 return "Lb1E";
4593 }
4594 elsif($TParam eq "false")
4595 { # class_name<true>::method(...)
4596 return "Lb0E";
4597 }
4598 else { # internal error
4599 return length($TParam).$TParam;
4600 }
4601}
4602
4603sub add_substitution($$$)
4604{
4605 my ($Value, $Repl, $Rec) = @_;
4606 if($Rec)
4607 { # subtypes
4608 my @Subs = ($Value);
4609 while($Value=~s/\A(R|P|K)//) {
4610 push(@Subs, $Value);
4611 }
4612 foreach (reverse(@Subs)) {
4613 add_substitution($_, $Repl, 0);
4614 }
4615 return;
4616 }
4617 return if($Value=~/\AS(\d*)_\Z/);
4618 $Value=~s/\AN(.+)E\Z/$1/g;
4619 return if(defined $Repl->{$Value});
4620 return if(length($Value)<=1);
4621 return if($StdcxxMangling{$Value});
4622 # check for duplicates
4623 my $Base = $Value;
4624 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4625 {
4626 my $Num = $Repl->{$Type};
4627 my $Replace = macro_mangle($Num);
4628 $Base=~s/\Q$Replace\E/$Type/;
4629 }
4630 if(my $OldNum = $Repl->{$Base})
4631 {
4632 $Repl->{$Value} = $OldNum;
4633 return;
4634 }
4635 my @Repls = sort {$b<=>$a} values(%{$Repl});
4636 if(@Repls) {
4637 $Repl->{$Value} = $Repls[0]+1;
4638 }
4639 else {
4640 $Repl->{$Value} = -1;
4641 }
4642 # register duplicates
4643 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004644 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004645 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4646 {
4647 next if($Base eq $Type);
4648 my $Num = $Repl->{$Type};
4649 my $Replace = macro_mangle($Num);
4650 $Base=~s/\Q$Type\E/$Replace/;
4651 $Repl->{$Base} = $Repl->{$Value};
4652 }
4653}
4654
4655sub macro_mangle($)
4656{
4657 my $Num = $_[0];
4658 if($Num==-1) {
4659 return "S_";
4660 }
4661 else
4662 {
4663 my $Code = "";
4664 if($Num<10)
4665 { # S0_, S1_, S2_, ...
4666 $Code = $Num;
4667 }
4668 elsif($Num>=10 and $Num<=35)
4669 { # SA_, SB_, SC_, ...
4670 $Code = chr(55+$Num);
4671 }
4672 else
4673 { # S10_, S11_, S12_
4674 $Code = $Num-26; # 26 is length of english alphabet
4675 }
4676 return "S".$Code."_";
4677 }
4678}
4679
4680sub write_stdcxx_substitution($)
4681{
4682 my $Mangled = $_[0];
4683 if($StdcxxMangling{$Mangled}) {
4684 return $StdcxxMangling{$Mangled};
4685 }
4686 else
4687 {
4688 my @Repls = keys(%StdcxxMangling);
4689 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4690 foreach my $MangledType (@Repls)
4691 {
4692 my $Replace = $StdcxxMangling{$MangledType};
4693 #if($Mangled!~/$Replace/) {
4694 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4695 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4696 #}
4697 }
4698 }
4699 return $Mangled;
4700}
4701
4702sub write_substitution($$)
4703{
4704 my ($Mangled, $Repl) = @_;
4705 if(defined $Repl->{$Mangled}
4706 and my $MnglNum = $Repl->{$Mangled}) {
4707 $Mangled = macro_mangle($MnglNum);
4708 }
4709 else
4710 {
4711 my @Repls = keys(%{$Repl});
4712 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4713 # FIXME: how to apply replacements? by num or by pos
4714 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4715 foreach my $MangledType (@Repls)
4716 {
4717 my $Replace = macro_mangle($Repl->{$MangledType});
4718 if($Mangled!~/$Replace/) {
4719 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4720 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4721 }
4722 }
4723 }
4724 return $Mangled;
4725}
4726
4727sub delete_keywords($)
4728{
4729 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004730 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004731 return $TypeName;
4732}
4733
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004734sub uncover_typedefs($$)
4735{
4736 my ($TypeName, $LibVersion) = @_;
4737 return "" if(not $TypeName);
4738 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4739 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4740 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004741 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004742 while($TypeName_New ne $TypeName_Pre)
4743 {
4744 $TypeName_Pre = $TypeName_New;
4745 my $TypeName_Copy = $TypeName_New;
4746 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004747 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004748 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004749 if(not $Intrinsic_Keywords{$1}) {
4750 $Words{$1} = 1;
4751 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004752 }
4753 foreach my $Word (keys(%Words))
4754 {
4755 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4756 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004757 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004758 if($BaseType_Name=~/\([\*]+\)/)
4759 { # FuncPtr
4760 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4761 {
4762 my $Type_Suffix = $1;
4763 $TypeName_New = $BaseType_Name;
4764 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004765 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004766 }
4767 }
4768 }
4769 else
4770 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004771 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004772 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004773 }
4774 }
4775 }
4776 }
4777 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4778}
4779
4780sub isInternal($)
4781{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004782 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4783 {
4784 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4785 {
4786 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4787 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4788 return 1;
4789 }
4790 }
4791 }
4792 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004793}
4794
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004795sub getDataVal($$)
4796{
4797 my ($InfoId, $TypeId) = @_;
4798 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4799 {
4800 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4801 {
4802 if(defined $LibInfo{$Version}{"info_type"}{$1}
4803 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004804 {
4805 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004806 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004807 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4808 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004809 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004810 if(my $Addr = getTreeAttr_Op($1)) {
4811 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004812 }
4813 }
4814 }
4815 }
4816 else {
4817 return getInitVal($1, $TypeId);
4818 }
4819 }
4820 }
4821 return undef;
4822}
4823
4824sub getInitVal($$)
4825{
4826 my ($InfoId, $TypeId) = @_;
4827 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4828 {
4829 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4830 {
4831 if($InfoType eq "integer_cst")
4832 {
4833 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004834 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004835 { # characters
4836 $Val = chr($Val);
4837 }
4838 return $Val;
4839 }
4840 elsif($InfoType eq "string_cst") {
4841 return getNodeStrCst($InfoId);
4842 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004843 elsif($InfoType eq "var_decl")
4844 {
4845 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4846 return $Name;
4847 }
4848 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004849 }
4850 }
4851 return undef;
4852}
4853
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004854sub set_Class_And_Namespace($)
4855{
4856 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004857 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004858 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004859 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004860 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004861 my $NSInfoId = $1;
4862 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4863 {
4864 if($InfoType eq "namespace_decl") {
4865 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4866 }
4867 elsif($InfoType eq "record_type") {
4868 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4869 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004870 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004871 }
4872 }
4873 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4874 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004875 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004876 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004877 { # skip
4878 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004879 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004880 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004881
4882 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004883}
4884
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004885sub debugMangling($)
4886{
4887 my $LibVersion = $_[0];
4888 my %Mangled = ();
4889 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4890 {
4891 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4892 {
4893 if($Mngl=~/\A(_Z|\?)/) {
4894 $Mangled{$Mngl}=$InfoId;
4895 }
4896 }
4897 }
4898 translateSymbols(keys(%Mangled), $LibVersion);
4899 foreach my $Mngl (keys(%Mangled))
4900 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004901 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4902 my $U2 = $tr_name{$Mngl};
4903 if($U1 ne $U2) {
4904 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004905 }
4906 }
4907}
4908
4909sub linkSymbol($)
4910{ # link symbols from shared libraries
4911 # with the symbols from header files
4912 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004913 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004914 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004915 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4916 or $EMERGENCY_MODE_48)
4917 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4918 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
4919 # GCC 4.8 doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004920 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004921 {
4922 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4923 return correct_incharge($InfoId, $Version, $Mangled);
4924 }
4925 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004926 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004927 or not $BinaryOnly
4928 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004929 { # 1. --headers-only mode
4930 # 2. not mangled src-only symbols
4931 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4932 return $Mangled;
4933 }
4934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004935 }
4936 return "";
4937}
4938
4939sub setLanguage($$)
4940{
4941 my ($LibVersion, $Lang) = @_;
4942 if(not $UserLang) {
4943 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4944 }
4945}
4946
4947sub getSymbolInfo($)
4948{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004949 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004950 if(isInternal($InfoId)) {
4951 return;
4952 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004953 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4954 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004955 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4956 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004957 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004958 return;
4959 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004960 setFuncAccess($InfoId);
4961 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004962 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4963 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004964 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004965 return;
4966 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004967
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004968 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004969 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004970 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004971 if(not defined $TypeInfo{$Version}{$Return}
4972 or not $TypeInfo{$Version}{$Return}{"Name"})
4973 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004974 delete($SymbolInfo{$Version}{$InfoId});
4975 return;
4976 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004977 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004978 }
4979 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
4980 {
4981 if(defined $MissedTypedef{$Version}{$Rid})
4982 {
4983 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
4984 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
4985 }
4986 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004987 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004988 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
4989 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004990 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004991 my $Orig = getFuncOrig($InfoId);
4992 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004993 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
4994 {
4995 delete($SymbolInfo{$Version}{$InfoId});
4996 return;
4997 }
4998
4999 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005000 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005001 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005002 return;
5003 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005004
5005 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005006 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005007 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5008
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005009 my @TParams = getTParams($Orig, "Func");
5010 if(not @TParams)
5011 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005012 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005013 return;
5014 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005015 foreach my $Pos (0 .. $#TParams)
5016 {
5017 my $Val = $TParams[$Pos];
5018 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5019
5020 if($Tmpl)
5021 {
5022 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5023 {
5024 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5025 }
5026 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005027 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005028
5029 if($Tmpl)
5030 {
5031 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5032 {
5033 if($Pos>$#TParams)
5034 {
5035 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5036 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5037 }
5038 }
5039 }
5040
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005041 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5042 { # operator<< <T>, operator>> <T>
5043 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5044 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005045 if(@TParams) {
5046 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5047 }
5048 else {
5049 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5050 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005051 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005052 }
5053 else
5054 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005055 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005056 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005057 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5058 {
5059 if($OSgroup eq "windows")
5060 { # cut the offset
5061 $MnglName=~s/\@\d+\Z//g;
5062 }
5063 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5064
5065 # NOTE: mangling of some symbols may change depending on GCC version
5066 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5067 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5068 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005069
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005070 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005071 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005072 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005073 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005074 return;
5075 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005076 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005077 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005078 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005079 if($Skip)
5080 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005081 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005082 return;
5083 }
5084 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005085 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5086 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5087 }
5088
5089 if(set_Class_And_Namespace($InfoId))
5090 {
5091 delete($SymbolInfo{$Version}{$InfoId});
5092 return;
5093 }
5094
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005095 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5096 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005097 if(not defined $TypeInfo{$Version}{$ClassId}
5098 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5099 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005100 delete($SymbolInfo{$Version}{$InfoId});
5101 return;
5102 }
5103 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005104 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5105 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005106 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005107 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005108 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005109 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005110 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005111 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005112 }
5113 if($COMMON_LANGUAGE{$Version} eq "C++")
5114 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005115 # C++ or --headers-only mode
5116 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005117 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005118 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5119 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005120 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005121 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005122 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005123 if(my $Mangled = linkSymbol($InfoId)) {
5124 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005125 }
5126 }
5127 if($OStarget eq "windows")
5128 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005129 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005130 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005131 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005132 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005133 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005134 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005135 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005136 }
5137 }
5138 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005139 else
5140 { # not mangled in C
5141 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5142 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005143 if(not $CheckHeadersOnly
5144 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5145 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5146 {
5147 my $Incorrect = 0;
5148
5149 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5150 {
5151 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5152 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5153 { # mangled in the TU dump, but not mangled in the library
5154 $Incorrect = 1;
5155 }
5156 }
5157 else
5158 {
5159 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5160 { # all C++ functions are not mangled in the TU dump
5161 $Incorrect = 1;
5162 }
5163 }
5164 if($Incorrect)
5165 {
5166 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5167 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5168 }
5169 }
5170 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005171 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005172 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005173 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005174 return;
5175 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005176 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005177 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005178 { # identify virtual and pure virtual functions
5179 # NOTE: constructors cannot be virtual
5180 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5181 # in the TU dump, so taking it from the original symbol
5182 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5183 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5184 { # NOTE: D2 destructors are not present in a v-table
5185 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5186 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005187 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005188 if(isInline($InfoId)) {
5189 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005190 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005191 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005192 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5193 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005194 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5195 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005196 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005197 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005198 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005199 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005200 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005201 }
5202 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005203 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5204 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005205 if(not $ExtraDump)
5206 {
5207 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5208 { # non-target symbols
5209 delete($SymbolInfo{$Version}{$InfoId});
5210 return;
5211 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005213 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005214 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5215 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5216 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5217 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005218 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005219 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5220 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005221 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005222 return;
5223 }
5224 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005225 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005226 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005227 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005228 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005229 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005230 return;
5231 }
5232 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005233 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005234 }
5235 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005236 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5237 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5238 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005239 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005240 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5241 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005242 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005243 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005244 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005245 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005246 }
5247 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005248 if(getFuncLink($InfoId) eq "Static") {
5249 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005250 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005251 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5252 {
5253 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5254 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005255 if($Unmangled=~/\.\_\d/)
5256 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005257 delete($SymbolInfo{$Version}{$InfoId});
5258 return;
5259 }
5260 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005261 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005262
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005263 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5264 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005265 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005266 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5267 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005268 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005269
5270 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5271 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5272 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005273
5274 if($ExtraDump) {
5275 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5276 }
5277}
5278
5279sub guessHeader($)
5280{
5281 my $InfoId = $_[0];
5282 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5283 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5284 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5285 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5286 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5287 {
5288 if(get_filename($HPath) eq $Header)
5289 {
5290 my $HDir = get_filename(get_dirname($HPath));
5291 if($HDir ne "include"
5292 and $HDir=~/\A[a-z]+\Z/i) {
5293 return join_P($HDir, $Header);
5294 }
5295 }
5296 }
5297 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005298}
5299
5300sub isInline($)
5301{ # "body: undefined" in the tree
5302 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005303 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5304 {
5305 if($Info=~/ undefined /i) {
5306 return 0;
5307 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005308 }
5309 return 1;
5310}
5311
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005312sub hasThrow($)
5313{
5314 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5315 {
5316 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5317 return getTreeAttr_Unql($1, "unql");
5318 }
5319 }
5320 return 1;
5321}
5322
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005323sub getTypeId($)
5324{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005325 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5326 {
5327 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5328 return $1;
5329 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005330 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005331 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005332}
5333
5334sub setTypeMemb($$)
5335{
5336 my ($TypeId, $TypeAttr) = @_;
5337 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005338 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005339 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005340 if($TypeType eq "Enum")
5341 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005342 my $MInfoId = getTreeAttr_Csts($TypeId);
5343 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005344 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005345 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5346 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005347 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005348 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5349 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005350 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005351 }
5352 }
5353 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5354 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005355 my $MInfoId = getTreeAttr_Flds($TypeId);
5356 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005357 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005358 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5359 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005360 if(not $IType or $IType ne "field_decl")
5361 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005362
5363 if($IType eq "var_decl")
5364 { # static field
5365 $StaticFields = 1;
5366 }
5367
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005368 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005369 next;
5370 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005371 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005372 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005373 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005374 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005375 }
5376 if(not $StructMembName)
5377 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005378 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005379 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005380 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005381 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5382 if(isAnon($UnnamedTName))
5383 { # rename unnamed fields to unnamed0, unnamed1, ...
5384 $StructMembName = "unnamed".($UnnamedPos++);
5385 }
5386 }
5387 }
5388 if(not $StructMembName)
5389 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005390 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005391 next;
5392 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005393 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005394 if(defined $MissedTypedef{$Version}{$MembTypeId})
5395 {
5396 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5397 $MembTypeId = $AddedTid;
5398 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005399 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005400
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005401 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5402 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005403 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005404 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005405 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5406 }
5407 if($MInfo=~/spec:\s*mutable /)
5408 { # mutable fields
5409 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005410 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005411 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005412 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5413 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005414 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005415 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005416 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005417 }
5418 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005419 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005420 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5421 { # template
5422 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5423 }
5424 else {
5425 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5426 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005427 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005428
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005429 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005430 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005431 }
5432 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005433
5434 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005435}
5436
5437sub setFuncParams($)
5438{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005439 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005440 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005441
5442 my $FType = getFuncType($InfoId);
5443
5444 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005445 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005446 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5447 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005448 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005449 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005450 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5451 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005452 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005453 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5454 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005455 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005456 else
5457 { # skip
5458 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005459 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005460 # skip "this"-parameter
5461 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005462 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005463 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005464 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005465 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005466 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5467 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5468 if(not $ParamName)
5469 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005470 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005471 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005472 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5473 {
5474 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5475 $ParamTypeId = $AddedTid;
5476 }
5477 }
5478 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005479 if(not $PType or $PType eq "Unknown") {
5480 return 1;
5481 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005482 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005483 if(not $PTName) {
5484 return 1;
5485 }
5486 if($PTName eq "void") {
5487 last;
5488 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005489 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005490 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005491 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005492 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005493 $ParamInfoId = getNextElem($ParamInfoId);
5494 next;
5495 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005496 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005497
5498 if(my %Base = get_BaseType($ParamTypeId, $Version))
5499 {
5500 if(defined $Base{"Template"}) {
5501 return 1;
5502 }
5503 }
5504
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005505 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005506 if(my $Algn = getAlgn($ParamInfoId)) {
5507 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5508 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005509 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5510 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005511 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005512 }
5513 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005514 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005515 if($ParamName ne "this" or $FType ne "Method") {
5516 $PPos += 1;
5517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005518 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005519 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005520 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005521 }
5522 return 0;
5523}
5524
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005525sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005526{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005527 my ($InfoId, $Vtt_Pos) = @_;
5528 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005529 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005530 my $FType = getFuncType($InfoId);
5531
5532 if($FType eq "Method")
5533 {
5534 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005535 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005536 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005537 if(not $ParamListElemId)
5538 { # foo(...)
5539 return 1;
5540 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005541 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005542 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005543 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005544 { # actual params: may differ from formal args
5545 # formal int*const
5546 # actual: int*
5547 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005548 {
5549 $Vtt_Pos=-1;
5550 $ParamListElemId = getNextElem($ParamListElemId);
5551 next;
5552 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005553 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5554 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005555 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005556 $HaveVoid = 1;
5557 last;
5558 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005559 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005560 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005561 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5562 {
5563 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5564 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5565 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005566 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005567 }
5568 }
5569 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5570 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005571 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005572 { # params
5573 if($OldId ne $ParamTypeId)
5574 {
5575 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5576 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5577
5578 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5579 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5580 }
5581 }
5582 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005583 }
5584 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005585 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005586 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005587 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5588 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005589 if($PurpType eq "nop_expr")
5590 { # func ( const char* arg = (const char*)(void*)0 )
5591 $PurpId = getTreeAttr_Op($PurpId);
5592 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005593 my $Val = getInitVal($PurpId, $ParamTypeId);
5594 if(defined $Val) {
5595 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5596 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005597 }
5598 }
5599 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005600 if($Pos!=0 or $FType ne "Method") {
5601 $PPos += 1;
5602 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005603 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005604 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005605 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005606}
5607
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005608sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005609{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005610 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5611 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005612 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5613 return $1;
5614 }
5615 }
5616 return "";
5617}
5618
5619sub getTreeAttr_Chain($)
5620{
5621 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5622 {
5623 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5624 return $1;
5625 }
5626 }
5627 return "";
5628}
5629
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005630sub getTreeAttr_Unql($)
5631{
5632 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5633 {
5634 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5635 return $1;
5636 }
5637 }
5638 return "";
5639}
5640
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005641sub getTreeAttr_Scpe($)
5642{
5643 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5644 {
5645 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5646 return $1;
5647 }
5648 }
5649 return "";
5650}
5651
5652sub getTreeAttr_Type($)
5653{
5654 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5655 {
5656 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5657 return $1;
5658 }
5659 }
5660 return "";
5661}
5662
5663sub getTreeAttr_Name($)
5664{
5665 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5666 {
5667 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5668 return $1;
5669 }
5670 }
5671 return "";
5672}
5673
5674sub getTreeAttr_Mngl($)
5675{
5676 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5677 {
5678 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5679 return $1;
5680 }
5681 }
5682 return "";
5683}
5684
5685sub getTreeAttr_Prms($)
5686{
5687 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5688 {
5689 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5690 return $1;
5691 }
5692 }
5693 return "";
5694}
5695
5696sub getTreeAttr_Fncs($)
5697{
5698 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5699 {
5700 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5701 return $1;
5702 }
5703 }
5704 return "";
5705}
5706
5707sub getTreeAttr_Csts($)
5708{
5709 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5710 {
5711 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5712 return $1;
5713 }
5714 }
5715 return "";
5716}
5717
5718sub getTreeAttr_Purp($)
5719{
5720 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5721 {
5722 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5723 return $1;
5724 }
5725 }
5726 return "";
5727}
5728
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005729sub getTreeAttr_Op($)
5730{
5731 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5732 {
5733 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5734 return $1;
5735 }
5736 }
5737 return "";
5738}
5739
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005740sub getTreeAttr_Valu($)
5741{
5742 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5743 {
5744 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5745 return $1;
5746 }
5747 }
5748 return "";
5749}
5750
5751sub getTreeAttr_Flds($)
5752{
5753 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5754 {
5755 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5756 return $1;
5757 }
5758 }
5759 return "";
5760}
5761
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005762sub getTreeAttr_Binf($)
5763{
5764 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5765 {
5766 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5767 return $1;
5768 }
5769 }
5770 return "";
5771}
5772
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005773sub getTreeAttr_Args($)
5774{
5775 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5776 {
5777 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005778 return $1;
5779 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005780 }
5781 return "";
5782}
5783
5784sub getTreeValue($)
5785{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005786 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5787 {
5788 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5789 return $1;
5790 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005791 }
5792 return "";
5793}
5794
5795sub getTreeAccess($)
5796{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005797 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005798 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005799 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5800 {
5801 my $Access = $1;
5802 if($Access eq "prot") {
5803 return "protected";
5804 }
5805 elsif($Access eq "priv") {
5806 return "private";
5807 }
5808 }
5809 elsif($Info=~/ protected /)
5810 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005811 return "protected";
5812 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005813 elsif($Info=~/ private /)
5814 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005815 return "private";
5816 }
5817 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005818 return "public";
5819}
5820
5821sub setFuncAccess($)
5822{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005823 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005824 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005825 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005826 }
5827 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005828 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005829 }
5830}
5831
5832sub setTypeAccess($$)
5833{
5834 my ($TypeId, $TypeAttr) = @_;
5835 my $Access = getTreeAccess($TypeId);
5836 if($Access eq "protected") {
5837 $TypeAttr->{"Protected"} = 1;
5838 }
5839 elsif($Access eq "private") {
5840 $TypeAttr->{"Private"} = 1;
5841 }
5842}
5843
5844sub setFuncKind($)
5845{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005846 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5847 {
5848 if($Info=~/pseudo tmpl/) {
5849 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5850 }
5851 elsif($Info=~/ constructor /) {
5852 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5853 }
5854 elsif($Info=~/ destructor /) {
5855 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5856 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005857 }
5858}
5859
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005860sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005861{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005862 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5863 {
5864 if($Info=~/spec[ ]*:[ ]*pure /) {
5865 return "PureVirt";
5866 }
5867 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5868 return "Virt";
5869 }
5870 elsif($Info=~/ pure\s+virtual /)
5871 { # support for old GCC versions
5872 return "PureVirt";
5873 }
5874 elsif($Info=~/ virtual /)
5875 { # support for old GCC versions
5876 return "Virt";
5877 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005878 }
5879 return "";
5880}
5881
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005882sub getFuncLink($)
5883{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005884 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5885 {
5886 if($Info=~/link[ ]*:[ ]*static /) {
5887 return "Static";
5888 }
5889 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005890 return $1;
5891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005892 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005893 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005894}
5895
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005896sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005897{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005898 my ($Symbol, $LibVersion) = @_;
5899 return "" if(not $Symbol or not $LibVersion);
5900 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5901 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005902 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005903 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5904 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5905 }
5906 }
5907 if($NS)
5908 {
5909 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5910 return $NS;
5911 }
5912 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005913 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005914 while($NS=~s/::[^:]+\Z//)
5915 {
5916 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5917 return $NS;
5918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005919 }
5920 }
5921 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005922
5923 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005924}
5925
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005926sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005927{
5928 my ($TypeName, $LibVersion) = @_;
5929 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005930 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005931 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005932 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5933 return $NS;
5934 }
5935 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005936 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005937 while($NS=~s/::[^:]+\Z//)
5938 {
5939 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5940 return $NS;
5941 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005942 }
5943 }
5944 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005945 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005946}
5947
5948sub getNameSpace($)
5949{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005950 my $InfoId = $_[0];
5951 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005952 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005953 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005954 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005955 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005956 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005957 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5958 {
5959 my $NameSpace = getTreeStr($1);
5960 if($NameSpace eq "::")
5961 { # global namespace
5962 return "";
5963 }
5964 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5965 $NameSpace = $BaseNameSpace."::".$NameSpace;
5966 }
5967 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5968 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005969 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005970 else {
5971 return "";
5972 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005973 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005974 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005975 { # inside data type
5976 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
5977 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005978 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005979 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005980 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005981 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005982}
5983
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005984sub getEnumMembVal($)
5985{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005986 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005987 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005988 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
5989 {
5990 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
5991 {
5992 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
5993 { # in newer versions of GCC the value is in the "const_decl->cnst" node
5994 return getTreeValue($1);
5995 }
5996 else
5997 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
5998 return getTreeValue($1);
5999 }
6000 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006001 }
6002 }
6003 return "";
6004}
6005
6006sub getSize($)
6007{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006008 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6009 {
6010 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6011 return getTreeValue($1);
6012 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006013 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006014 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006015}
6016
6017sub getAlgn($)
6018{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006019 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6020 {
6021 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6022 return $1;
6023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006024 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006025 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006026}
6027
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006028sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006029{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006030 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6031 {
6032 if($Info=~/ bitfield /) {
6033 return getSize($_[0]);
6034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006035 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006036 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006037}
6038
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006039sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006040{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006041 if(my $Chan = getTreeAttr_Chan($_[0])) {
6042 return $Chan;
6043 }
6044 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6045 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006046 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006047 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006048}
6049
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006050sub registerHeader($$)
6051{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006052 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006053 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006054 return "";
6055 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006056 if(is_abs($Header) and not -f $Header)
6057 { # incorrect absolute path
6058 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006059 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006060 if(skipHeader($Header, $LibVersion))
6061 { # skip
6062 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006063 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006064 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6065 {
6066 detect_header_includes($Header_Path, $LibVersion);
6067
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006068 if(defined $Tolerance and $Tolerance=~/3/)
6069 { # 3 - skip headers that include non-Linux headers
6070 if($OSgroup ne "windows")
6071 {
6072 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6073 {
6074 if(specificHeader($Inc, "windows")) {
6075 return "";
6076 }
6077 }
6078 }
6079 }
6080
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006081 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6082 { # redirect
6083 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6084 or skipHeader($RHeader_Path, $LibVersion))
6085 { # skip
6086 return "";
6087 }
6088 $Header_Path = $RHeader_Path;
6089 }
6090 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6091 { # skip
6092 return "";
6093 }
6094
6095 if(my $HName = get_filename($Header_Path))
6096 { # register
6097 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6098 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6099 }
6100
6101 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6102 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006103 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006104 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006105 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006106 }
6107
6108 if($CheckHeadersOnly
6109 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6110 { # /usr/include/c++/4.6.1/...
6111 $STDCXX_TESTING = 1;
6112 }
6113
6114 return $Header_Path;
6115 }
6116 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006117}
6118
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006119sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006120{
6121 my ($Dir, $WithDeps, $LibVersion) = @_;
6122 $Dir=~s/[\/\\]+\Z//g;
6123 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006124 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006125
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006126 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006127 if($WithDeps)
6128 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006129 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6130 return;
6131 }
6132 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6133 $Mode = "DepsOnly";
6134 }
6135 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006136 else
6137 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006138 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6139 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6140 return;
6141 }
6142 }
6143 $Header_Dependency{$LibVersion}{$Dir} = 1;
6144 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6145 if($Mode eq "DepsOnly")
6146 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006147 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006148 $Header_Dependency{$LibVersion}{$Path} = 1;
6149 }
6150 return;
6151 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006152 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006153 {
6154 if($WithDeps)
6155 {
6156 my $SubDir = $Path;
6157 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6158 { # register all sub directories
6159 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6160 }
6161 }
6162 next if(is_not_header($Path));
6163 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006164 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006165 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006166 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6167 }
6168 }
6169 if(get_filename($Dir) eq "include")
6170 { # search for "lib/include/" directory
6171 my $LibDir = $Dir;
6172 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006173 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006174 }
6175 }
6176}
6177
6178sub parse_redirect($$$)
6179{
6180 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006181 my @Errors = ();
6182 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6183 push(@Errors, $1);
6184 }
6185 my $Redirect = "";
6186 foreach (@Errors)
6187 {
6188 s/\s{2,}/ /g;
6189 if(/(only|must\ include
6190 |update\ to\ include
6191 |replaced\ with
6192 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006193 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006194 {
6195 $Redirect = $2;
6196 last;
6197 }
6198 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6199 {
6200 $Redirect = $2;
6201 last;
6202 }
6203 elsif(/this\ header\ should\ not\ be\ used
6204 |programs\ should\ not\ directly\ include
6205 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6206 |is\ not\ supported\ API\ for\ general\ use
6207 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006208 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006209 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6210 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6211 }
6212 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006213 if($Redirect)
6214 {
6215 $Redirect=~s/\A<//g;
6216 $Redirect=~s/>\Z//g;
6217 }
6218 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006219}
6220
6221sub parse_includes($$)
6222{
6223 my ($Content, $Path) = @_;
6224 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006225 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006226 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006227 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006228 my $Method = substr($Header, 0, 1, "");
6229 substr($Header, length($Header)-1, 1, "");
6230 $Header = path_format($Header, $OSgroup);
6231 if($Method eq "\"" or is_abs($Header))
6232 {
6233 if(-e join_P(get_dirname($Path), $Header))
6234 { # relative path exists
6235 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006236 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006237 else
6238 { # include "..." that doesn't exist is equal to include <...>
6239 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006240 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006241 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006242 else {
6243 $Includes{$Header} = 1;
6244 }
6245 }
6246 if($ExtraInfo)
6247 {
6248 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6249 { # FT_FREETYPE_H
6250 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006251 }
6252 }
6253 return \%Includes;
6254}
6255
6256sub ignore_path($)
6257{
6258 my $Path = $_[0];
6259 if($Path=~/\~\Z/)
6260 {# skipping system backup files
6261 return 1;
6262 }
6263 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6264 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6265 return 1;
6266 }
6267 return 0;
6268}
6269
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006270sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006271{
6272 my ($ArrRef, $W) = @_;
6273 return if(length($W)<2);
6274 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6275}
6276
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006277sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006278{
6279 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006280
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006281 $H1=~s/\.[a-z]+\Z//ig;
6282 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006283
6284 my $Hname1 = get_filename($H1);
6285 my $Hname2 = get_filename($H2);
6286 my $HDir1 = get_dirname($H1);
6287 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006288 my $Dirname1 = get_filename($HDir1);
6289 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006290
6291 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6292 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6293
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006294 if($_[0] eq $_[1]
6295 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006296 return 0;
6297 }
6298 elsif($H1=~/\A\Q$H2\E/) {
6299 return 1;
6300 }
6301 elsif($H2=~/\A\Q$H1\E/) {
6302 return -1;
6303 }
6304 elsif($HDir1=~/\Q$Hname1\E/i
6305 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006306 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006307 return -1;
6308 }
6309 elsif($HDir2=~/\Q$Hname2\E/i
6310 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006311 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006312 return 1;
6313 }
6314 elsif($Hname1=~/\Q$Dirname1\E/i
6315 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006316 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006317 return -1;
6318 }
6319 elsif($Hname2=~/\Q$Dirname2\E/i
6320 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006321 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006322 return 1;
6323 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006324 elsif($Hname1=~/(config|lib|util)/i
6325 and $Hname2!~/(config|lib|util)/i)
6326 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006327 return -1;
6328 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006329 elsif($Hname2=~/(config|lib|util)/i
6330 and $Hname1!~/(config|lib|util)/i)
6331 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006332 return 1;
6333 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006334 else
6335 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006336 my $R1 = checkRelevance($H1);
6337 my $R2 = checkRelevance($H2);
6338 if($R1 and not $R2)
6339 { # libebook/e-book.h
6340 return -1;
6341 }
6342 elsif($R2 and not $R1)
6343 { # libebook/e-book.h
6344 return 1;
6345 }
6346 else
6347 {
6348 return (lc($H1) cmp lc($H2));
6349 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006350 }
6351}
6352
6353sub searchForHeaders($)
6354{
6355 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006356
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006357 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006358 registerGccHeaders();
6359
6360 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6361 { # c++ standard include paths
6362 registerCppHeaders();
6363 }
6364
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006365 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006366 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6367 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006368 {
6369 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006370 if($SystemRoot)
6371 {
6372 if(is_abs($Path)) {
6373 $Path = $SystemRoot.$Path;
6374 }
6375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006376 if(not -e $Path) {
6377 exitStatus("Access_Error", "can't access \'$Path\'");
6378 }
6379 elsif(-f $Path) {
6380 exitStatus("Access_Error", "\'$Path\' - not a directory");
6381 }
6382 elsif(-d $Path)
6383 {
6384 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006385 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006386 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6387 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006388 }
6389 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006390 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006391 }
6392 }
6393 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006394 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006395 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6396 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006397
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006398 # registering directories
6399 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6400 {
6401 next if(not -e $Path);
6402 $Path = get_abs_path($Path);
6403 $Path = path_format($Path, $OSgroup);
6404 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006405 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006406 }
6407 elsif(-f $Path)
6408 {
6409 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006410 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006411 and not $LocalIncludes{$Dir})
6412 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006413 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006414 # if(my $OutDir = get_dirname($Dir))
6415 # { # registering the outer directory
6416 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6417 # and not $LocalIncludes{$OutDir}) {
6418 # registerDir($OutDir, 0, $LibVersion);
6419 # }
6420 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006421 }
6422 }
6423 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006424
6425 # clean memory
6426 %RegisteredDirs = ();
6427
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006428 # registering headers
6429 my $Position = 0;
6430 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6431 {
6432 if(is_abs($Dest) and not -e $Dest) {
6433 exitStatus("Access_Error", "can't access \'$Dest\'");
6434 }
6435 $Dest = path_format($Dest, $OSgroup);
6436 if(is_header($Dest, 1, $LibVersion))
6437 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006438 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006439 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6440 }
6441 }
6442 elsif(-d $Dest)
6443 {
6444 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006445 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006446 {
6447 next if(ignore_path($Path));
6448 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006449 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006450 push(@Registered, $HPath);
6451 }
6452 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006453 @Registered = sort {sortHeaders($a, $b)} @Registered;
6454 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006455 foreach my $Path (@Registered) {
6456 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6457 }
6458 }
6459 else {
6460 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6461 }
6462 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006463
6464 if(defined $Tolerance and $Tolerance=~/4/)
6465 { # 4 - skip headers included by others
6466 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6467 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006468 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006469 delete($Registered_Headers{$LibVersion}{$Path});
6470 }
6471 }
6472 }
6473
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006474 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6475 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006476 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006477 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006478 if(is_abs($Header) and not -f $Header) {
6479 exitStatus("Access_Error", "can't access file \'$Header\'");
6480 }
6481 $Header = path_format($Header, $OSgroup);
6482 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6483 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006484 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006485 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006486 }
6487 else {
6488 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6489 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006490 }
6491 }
6492 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6493 { # set relative paths (for duplicates)
6494 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6495 { # search for duplicates
6496 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6497 my $Prefix = get_dirname($FirstPath);
6498 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6499 { # detect a shortest distinguishing prefix
6500 my $NewPrefix = $1;
6501 my %Identity = ();
6502 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6503 {
6504 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6505 $Identity{$Path} = $1;
6506 }
6507 }
6508 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006509 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006510 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6511 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6512 }
6513 last;
6514 }
6515 $Prefix = $NewPrefix; # increase prefix
6516 }
6517 }
6518 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006519
6520 # clean memory
6521 %HeaderName_Paths = ();
6522
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006523 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6524 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006525 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006526 my ($Pos, $PairPos) = (-1, -1);
6527 my ($Path, $PairPath) = ();
6528 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6529 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6530 foreach my $Header_Path (@Paths)
6531 {
6532 if(get_filename($Header_Path) eq $PairName)
6533 {
6534 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6535 $PairPath = $Header_Path;
6536 }
6537 if(get_filename($Header_Path) eq $HeaderName)
6538 {
6539 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6540 $Path = $Header_Path;
6541 }
6542 }
6543 if($PairPos!=-1 and $Pos!=-1
6544 and int($PairPos)<int($Pos))
6545 {
6546 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6547 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6548 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6549 }
6550 }
6551 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6552 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6553 }
6554}
6555
6556sub detect_real_includes($$)
6557{
6558 my ($AbsPath, $LibVersion) = @_;
6559 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6560 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6561 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6562 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6563 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006564 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6565
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006566 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6567 return () if(not $Path);
6568 open(PREPROC, $Path);
6569 while(<PREPROC>)
6570 {
6571 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6572 {
6573 my $Include = path_format($1, $OSgroup);
6574 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6575 next;
6576 }
6577 if($Include eq $AbsPath) {
6578 next;
6579 }
6580 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6581 }
6582 }
6583 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006584 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6585}
6586
6587sub detect_header_includes($$)
6588{
6589 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006590 return if(not $LibVersion or not $Path);
6591 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6592 return;
6593 }
6594 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6595
6596 if(not -e $Path) {
6597 return;
6598 }
6599
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006600 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006601 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6602 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006603 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006604 {
6605 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006606 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006607 }
6608 if($RedirectPath ne $Path) {
6609 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6610 }
6611 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006612 else
6613 { # can't find
6614 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006616 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006617 if(my $Inc = parse_includes($Content, $Path))
6618 {
6619 foreach my $Include (keys(%{$Inc}))
6620 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006621 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006622
6623 if(defined $Tolerance and $Tolerance=~/4/)
6624 {
6625 if(my $HPath = identifyHeader($Include, $LibVersion))
6626 {
6627 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6628 }
6629 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006630 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006631 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006632}
6633
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006634sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006635{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006636 my $Path = $_[0];
6637 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006638 if($OStarget eq "symbian")
6639 {
6640 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6641 { # epoc32/include/libc/{stdio, ...}.h
6642 return 1;
6643 }
6644 }
6645 else
6646 {
6647 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6648 { # /usr/include/{stdio, ...}.h
6649 return 1;
6650 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006652 return 0;
6653}
6654
6655sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006656{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006657 my $Dir = $_[0];
6658 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006659 if($OStarget eq "symbian")
6660 {
6661 if(get_filename($OutDir) eq "libc"
6662 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6663 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6664 return 1;
6665 }
6666 }
6667 else
6668 { # linux
6669 if($OutDir eq "/usr/include"
6670 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6671 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6672 return 1;
6673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006674 }
6675 return 0;
6676}
6677
6678sub detect_recursive_includes($$)
6679{
6680 my ($AbsPath, $LibVersion) = @_;
6681 return () if(not $AbsPath);
6682 if(isCyclical(\@RecurInclude, $AbsPath)) {
6683 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6684 }
6685 my ($AbsDir, $Name) = separate_path($AbsPath);
6686 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006687 { # system GLIBC internals
6688 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006689 }
6690 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6691 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6692 }
6693 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006694
6695 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6696 { # skip /usr/include/c++/*/ headers
6697 return () if(not $ExtraInfo);
6698 }
6699
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006700 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006701 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006702 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006703 { # check "real" (non-"model") include paths
6704 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6705 pop(@RecurInclude);
6706 return @Paths;
6707 }
6708 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6709 detect_header_includes($AbsPath, $LibVersion);
6710 }
6711 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6712 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006713 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006714 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006715 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006716 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006717 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006718 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006719 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006720 }
6721 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006722 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006723 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006724 { # search for the nearest header
6725 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006726 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006727 if(-f $Candidate) {
6728 $HPath = $Candidate;
6729 }
6730 }
6731 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006732 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006733 }
6734 next if(not $HPath);
6735 if($HPath eq $AbsPath) {
6736 next;
6737 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006738
6739 if($Debug)
6740 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006741# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6742# {
6743# print STDERR "$AbsPath -> $HPath\n";
6744# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006745 }
6746
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006747 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6748 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006749 { # only include <...>, skip include "..." prefixes
6750 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6751 }
6752 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6753 {
6754 if($IncPath eq $AbsPath) {
6755 next;
6756 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006757 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6758 if($RIncType==-1)
6759 { # include "..."
6760 $RIncType = $IncType;
6761 }
6762 elsif($RIncType==2)
6763 {
6764 if($IncType!=-1) {
6765 $RIncType = $IncType;
6766 }
6767 }
6768 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006769 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6770 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6771 }
6772 }
6773 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6774 {
6775 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6776 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6777 { # distinguish math.h from glibc and math.h from the tested library
6778 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6779 last;
6780 }
6781 }
6782 }
6783 pop(@RecurInclude);
6784 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6785}
6786
6787sub find_in_framework($$$)
6788{
6789 my ($Header, $Framework, $LibVersion) = @_;
6790 return "" if(not $Header or not $Framework or not $LibVersion);
6791 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6792 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6793 }
6794 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6795 {
6796 if(get_filename($Dependency) eq $Framework
6797 and -f get_dirname($Dependency)."/".$Header) {
6798 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6799 }
6800 }
6801 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6802}
6803
6804sub find_in_defaults($)
6805{
6806 my $Header = $_[0];
6807 return "" if(not $Header);
6808 if(defined $Cache{"find_in_defaults"}{$Header}) {
6809 return $Cache{"find_in_defaults"}{$Header};
6810 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006811 foreach my $Dir (@DefaultIncPaths,
6812 @DefaultGccPaths,
6813 @DefaultCppPaths,
6814 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006815 {
6816 next if(not $Dir);
6817 if(-f $Dir."/".$Header) {
6818 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6819 }
6820 }
6821 return ($Cache{"find_in_defaults"}{$Header}="");
6822}
6823
6824sub cmp_paths($$)
6825{
6826 my ($Path1, $Path2) = @_;
6827 my @Parts1 = split(/[\/\\]/, $Path1);
6828 my @Parts2 = split(/[\/\\]/, $Path2);
6829 foreach my $Num (0 .. $#Parts1)
6830 {
6831 my $Part1 = $Parts1[$Num];
6832 my $Part2 = $Parts2[$Num];
6833 if($GlibcDir{$Part1}
6834 and not $GlibcDir{$Part2}) {
6835 return 1;
6836 }
6837 elsif($GlibcDir{$Part2}
6838 and not $GlibcDir{$Part1}) {
6839 return -1;
6840 }
6841 elsif($Part1=~/glib/
6842 and $Part2!~/glib/) {
6843 return 1;
6844 }
6845 elsif($Part1!~/glib/
6846 and $Part2=~/glib/) {
6847 return -1;
6848 }
6849 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6850 return $CmpRes;
6851 }
6852 }
6853 return 0;
6854}
6855
6856sub checkRelevance($)
6857{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006858 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006859 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006860
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006861 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006862 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006863 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006864
6865 my $Name = lc(get_filename($Path));
6866 my $Dir = lc(get_dirname($Path));
6867
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006868 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006869
6870 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006871 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006872 my $Len = length($Token);
6873 next if($Len<=1);
6874 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6875 { # include/evolution-data-server-1.4/libebook/e-book.h
6876 return 1;
6877 }
6878 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006879 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006880 return 1;
6881 }
6882 }
6883 return 0;
6884}
6885
6886sub checkFamily(@)
6887{
6888 my @Paths = @_;
6889 return 1 if($#Paths<=0);
6890 my %Prefix = ();
6891 foreach my $Path (@Paths)
6892 {
6893 if($SystemRoot) {
6894 $Path = cut_path_prefix($Path, $SystemRoot);
6895 }
6896 if(my $Dir = get_dirname($Path))
6897 {
6898 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6899 $Prefix{$Dir} += 1;
6900 $Prefix{get_dirname($Dir)} += 1;
6901 }
6902 }
6903 foreach (sort keys(%Prefix))
6904 {
6905 if(get_depth($_)>=3
6906 and $Prefix{$_}==$#Paths+1) {
6907 return 1;
6908 }
6909 }
6910 return 0;
6911}
6912
6913sub isAcceptable($$$)
6914{
6915 my ($Header, $Candidate, $LibVersion) = @_;
6916 my $HName = get_filename($Header);
6917 if(get_dirname($Header))
6918 { # with prefix
6919 return 1;
6920 }
6921 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6922 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6923 return 1;
6924 }
6925 if(checkRelevance($Candidate))
6926 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6927 return 1;
6928 }
6929 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6930 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6931 # /usr/include/qt4/Qt/qsslconfiguration.h
6932 return 1;
6933 }
6934 if($OStarget eq "symbian")
6935 {
6936 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6937 return 1;
6938 }
6939 }
6940 return 0;
6941}
6942
6943sub isRelevant($$$)
6944{ # disallow to search for "abstract" headers in too deep directories
6945 my ($Header, $Candidate, $LibVersion) = @_;
6946 my $HName = get_filename($Header);
6947 if($OStarget eq "symbian")
6948 {
6949 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6950 return 0;
6951 }
6952 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006953 if($OStarget ne "bsd")
6954 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006955 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6956 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6957 return 0;
6958 }
6959 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006960 if($OStarget ne "windows")
6961 {
6962 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6963 { # skip /usr/include/wine/msvcrt
6964 return 0;
6965 }
6966 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006967 if(not get_dirname($Header)
6968 and $Candidate=~/[\/\\]wx[\/\\]/)
6969 { # do NOT search in system /wx/ directory
6970 # for headers without a prefix: sstream.h
6971 return 0;
6972 }
6973 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
6974 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
6975 { # skip ../c++/3.3.3/ if using ../c++/4.5/
6976 return 0;
6977 }
6978 if($Candidate=~/[\/\\]asm-/
6979 and (my $Arch = getArch($LibVersion)) ne "unknown")
6980 { # arch-specific header files
6981 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
6982 {# skip ../asm-arm/ if using x86 architecture
6983 return 0;
6984 }
6985 }
6986 my @Candidates = getSystemHeaders($HName, $LibVersion);
6987 if($#Candidates==1)
6988 { # unique header
6989 return 1;
6990 }
6991 my @SCandidates = getSystemHeaders($Header, $LibVersion);
6992 if($#SCandidates==1)
6993 { # unique name
6994 return 1;
6995 }
6996 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
6997 if(get_depth($Candidate)-$SystemDepth>=5)
6998 { # abstract headers in too deep directories
6999 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7000 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7001 return 0;
7002 }
7003 }
7004 if($Header eq "parser.h"
7005 and $Candidate!~/\/libxml2\//)
7006 { # select parser.h from xml2 library
7007 return 0;
7008 }
7009 if(not get_dirname($Header)
7010 and keys(%{$SystemHeaders{$HName}})>=3)
7011 { # many headers with the same name
7012 # like thread.h included without a prefix
7013 if(not checkFamily(@Candidates)) {
7014 return 0;
7015 }
7016 }
7017 return 1;
7018}
7019
7020sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007021{ # cache function
7022 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7023 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7024 }
7025 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7026}
7027
7028sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007029{
7030 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007031 if(-f $Header) {
7032 return $Header;
7033 }
7034 if(is_abs($Header) and not -f $Header)
7035 { # incorrect absolute path
7036 return "";
7037 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007038 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007039 { # too abstract configuration headers
7040 return "";
7041 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007042 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007043 if($OSgroup ne "windows")
7044 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007045 if(defined $WinHeaders{lc($HName)}
7046 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007047 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007048 return "";
7049 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007050 }
7051 if($OSgroup ne "macos")
7052 {
7053 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007054 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007055 return "";
7056 }
7057 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007058
7059 if(defined $ObsoleteHeaders{$HName})
7060 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007061 return "";
7062 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007063 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7064 {
7065 if(defined $AlienHeaders{$HName}
7066 or defined $AlienHeaders{$Header})
7067 { # alien headers from other systems
7068 return "";
7069 }
7070 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007071
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007072 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007073 { # search in default paths
7074 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007075 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007076 }
7077 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007078 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007079 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007080 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007081 }
7082 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7083 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7084 {
7085 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007086 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007087 }
7088 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007089 # error
7090 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007091}
7092
7093sub getSystemHeaders($$)
7094{
7095 my ($Header, $LibVersion) = @_;
7096 my @Candidates = ();
7097 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7098 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007099 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007100 next;
7101 }
7102 push(@Candidates, $Candidate);
7103 }
7104 return @Candidates;
7105}
7106
7107sub cut_path_prefix($$)
7108{
7109 my ($Path, $Prefix) = @_;
7110 return $Path if(not $Prefix);
7111 $Prefix=~s/[\/\\]+\Z//;
7112 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7113 return $Path;
7114}
7115
7116sub is_default_include_dir($)
7117{
7118 my $Dir = $_[0];
7119 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007120 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007121}
7122
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007123sub identifyHeader($$)
7124{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007125 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007126 if(not $Header) {
7127 return "";
7128 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007129 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007130 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7131 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007132 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007133 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007134}
7135
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007136sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007137{ # search for header by absolute path, relative path or name
7138 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007139 if(-f $Header)
7140 { # it's relative or absolute path
7141 return get_abs_path($Header);
7142 }
7143 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7144 and my $HeaderDir = find_in_defaults($Header))
7145 { # search for libc headers in the /usr/include
7146 # for non-libc target library before searching
7147 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007148 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007149 }
7150 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7151 { # search in the target library paths
7152 return $Path;
7153 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007154 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007155 { # search in the internal GCC include paths
7156 return $DefaultGccHeader{$Header};
7157 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007158 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007159 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007160 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007161 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007162 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007163 { # search in the default G++ include paths
7164 return $DefaultCppHeader{$Header};
7165 }
7166 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7167 { # search everywhere in the system
7168 return $AnyPath;
7169 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007170 elsif($OSgroup eq "macos")
7171 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7172 if(my $Dir = get_dirname($Header))
7173 {
7174 my $RelPath = "Headers\/".get_filename($Header);
7175 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007176 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007177 }
7178 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007179 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007180 # cannot find anything
7181 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007182}
7183
7184sub getLocation($)
7185{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007186 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7187 {
7188 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007189 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007190 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007191 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007192 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007193}
7194
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007195sub getNameByInfo($)
7196{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007197 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007198 {
7199 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7200 {
7201 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7202 {
7203 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7204 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007205 my $Str = $1;
7206 if($CppMode{$Version}
7207 and $Str=~/\Ac99_(.+)\Z/)
7208 {
7209 if($CppKeywords_A{$1}) {
7210 $Str=$1;
7211 }
7212 }
7213 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007214 }
7215 }
7216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007217 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007218 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007219}
7220
7221sub getTreeStr($)
7222{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007223 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007224 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007225 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7226 {
7227 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007228 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007229 and $Str=~/\Ac99_(.+)\Z/)
7230 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007231 if($CppKeywords_A{$1}) {
7232 $Str=$1;
7233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007234 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007235 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007236 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007237 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007238 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007239}
7240
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007241sub getFuncShortName($)
7242{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007243 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007244 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007245 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007246 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007247 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007248 {
7249 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7250 {
7251 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7252 return "operator ".$RName;
7253 }
7254 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007255 }
7256 else
7257 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007258 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7259 {
7260 if(my $Ind = $Operator_Indication{$1}) {
7261 return "operator".$Ind;
7262 }
7263 elsif(not $UnknownOperator{$1})
7264 {
7265 printMsg("WARNING", "unknown operator $1");
7266 $UnknownOperator{$1} = 1;
7267 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007268 }
7269 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007270 }
7271 else
7272 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007273 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7274 return getTreeStr($1);
7275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007276 }
7277 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007278 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007279}
7280
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007281sub getFuncReturn($)
7282{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007283 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7284 {
7285 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7286 {
7287 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7288 return $1;
7289 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007290 }
7291 }
7292 return "";
7293}
7294
7295sub getFuncOrig($)
7296{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007297 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7298 {
7299 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7300 return $1;
7301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007302 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007303 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007304}
7305
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007306sub unmangleArray(@)
7307{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007308 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007309 { # MSVC mangling
7310 my $UndNameCmd = get_CmdPath("undname");
7311 if(not $UndNameCmd) {
7312 exitStatus("Not_Found", "can't find \"undname\"");
7313 }
7314 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007315 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007316 }
7317 else
7318 { # GCC mangling
7319 my $CppFiltCmd = get_CmdPath("c++filt");
7320 if(not $CppFiltCmd) {
7321 exitStatus("Not_Found", "can't find c++filt in PATH");
7322 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007323 if(not defined $CPPFILT_SUPPORT_FILE)
7324 {
7325 my $Info = `$CppFiltCmd -h 2>&1`;
7326 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7327 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007328 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007329 if($CPPFILT_SUPPORT_FILE)
7330 { # new versions of c++filt can take a file
7331 if($#_>$MAX_CPPFILT_FILE_SIZE)
7332 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7333 # this is fixed in the oncoming version of Binutils
7334 my @Half = splice(@_, 0, ($#_+1)/2);
7335 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007336 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007337 else
7338 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007339 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7340 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7341 if($?==139)
7342 { # segmentation fault
7343 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7344 }
7345 return split(/\n/, $Res);
7346 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007347 }
7348 else
7349 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007350 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7351 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007352 my @Half = splice(@_, 0, ($#_+1)/2);
7353 return (unmangleArray(@Half), unmangleArray(@_))
7354 }
7355 else
7356 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007357 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007358 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7359 if($?==139)
7360 { # segmentation fault
7361 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7362 }
7363 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007364 }
7365 }
7366 }
7367}
7368
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007369sub get_ChargeLevel($$)
7370{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007371 my ($Symbol, $LibVersion) = @_;
7372 return "" if($Symbol!~/\A(_Z|\?)/);
7373 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7374 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007375 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007376 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007377 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007378 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007379 return "[in-charge]";
7380 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007381 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007382 return "[not-in-charge]";
7383 }
7384 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007385 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007386 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007387 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007388 return "[in-charge]";
7389 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007390 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007391 return "[not-in-charge]";
7392 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007393 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007394 return "[in-charge-deleting]";
7395 }
7396 }
7397 }
7398 else
7399 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007400 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007401 return "[in-charge]";
7402 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007403 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007404 return "[not-in-charge]";
7405 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007406 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007407 return "[in-charge]";
7408 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007409 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007410 return "[not-in-charge]";
7411 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007412 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007413 return "[in-charge-deleting]";
7414 }
7415 }
7416 return "";
7417}
7418
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007419sub get_Signature_M($$)
7420{
7421 my ($Symbol, $LibVersion) = @_;
7422 my $Signature_M = $tr_name{$Symbol};
7423 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7424 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007425 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007426 }
7427 return $Signature_M;
7428}
7429
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007430sub get_Signature($$)
7431{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007432 my ($Symbol, $LibVersion) = @_;
7433 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7434 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007435 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007436 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007437 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007438
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007439 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7440 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007441 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007442 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7443 {
7444 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7445 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7446 $Signature .= "~";
7447 }
7448 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007449 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007450 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007451 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007452 }
7453 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007454 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007455 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007456 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7457 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007458 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007459 else
7460 {
7461 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007462 }
7463 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007464 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007465 {
7466 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007467 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007468 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007469 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007470 if(not $ParamTypeName) {
7471 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7472 }
7473 foreach my $Typedef (keys(%ChangedTypedef))
7474 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007475 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7476 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7477 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007478 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007479 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7480 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007481 if($ParamName eq "this"
7482 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007483 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007484 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007485 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007486 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007487 }
7488 else {
7489 push(@ParamArray, $ParamTypeName);
7490 }
7491 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007492 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7493 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007494 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007495 }
7496 else
7497 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007498 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007499 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007500 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007501 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007502 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007503 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7504 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007505 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007506 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007507 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7508 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007509 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007510 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007511 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7512 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007513 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007514 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007515 }
7516 }
7517 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007518 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007519 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007520 }
7521 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007522 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007523 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007524 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007525}
7526
7527sub create_member_decl($$)
7528{
7529 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007530 if($TName=~/\([\*]+\)/)
7531 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007532 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7533 return $TName;
7534 }
7535 else
7536 {
7537 my @ArraySizes = ();
7538 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7539 push(@ArraySizes, $1);
7540 }
7541 return $TName." ".$Member.join("", @ArraySizes);
7542 }
7543}
7544
7545sub getFuncType($)
7546{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007547 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7548 {
7549 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7550 {
7551 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7552 {
7553 if($Type eq "method_type") {
7554 return "Method";
7555 }
7556 elsif($Type eq "function_type") {
7557 return "Function";
7558 }
7559 else {
7560 return "Other";
7561 }
7562 }
7563 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007564 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007565 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007566}
7567
7568sub getFuncTypeId($)
7569{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007570 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7571 {
7572 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7573 return $1;
7574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007575 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007576 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007577}
7578
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007579sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007580{ # "._N" or "$_N" in older GCC versions
7581 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007582}
7583
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007584sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007585{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007586 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7587 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007588 }
7589
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007590 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007591
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007592 if($_[1] ne "S")
7593 {
7594 $N=~s/\A[ ]+//g;
7595 $N=~s/[ ]+\Z//g;
7596 $N=~s/[ ]{2,}/ /g;
7597 }
7598
7599 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007600
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007601 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007602
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007603 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7604 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007605
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007606 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007607
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007608 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007609
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007610 if($_[1] eq "S")
7611 {
7612 if(index($N, "operator")!=-1) {
7613 $N=~s/\b(operator[ ]*)> >/$1>>/;
7614 }
7615 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007616
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007617 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007618}
7619
7620sub get_HeaderDeps($$)
7621{
7622 my ($AbsPath, $LibVersion) = @_;
7623 return () if(not $AbsPath or not $LibVersion);
7624 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7625 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7626 }
7627 my %IncDir = ();
7628 detect_recursive_includes($AbsPath, $LibVersion);
7629 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7630 {
7631 next if(not $HeaderPath);
7632 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7633 my $Dir = get_dirname($HeaderPath);
7634 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7635 {
7636 my $Dep = $Dir;
7637 if($Prefix)
7638 {
7639 if($OSgroup eq "windows")
7640 { # case insensitive seach on windows
7641 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7642 next;
7643 }
7644 }
7645 elsif($OSgroup eq "macos")
7646 { # seach in frameworks
7647 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7648 {
7649 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7650 {# frameworks
7651 my ($HFramework, $HName) = ($1, $2);
7652 $Dep = $HFramework;
7653 }
7654 else
7655 {# mismatch
7656 next;
7657 }
7658 }
7659 }
7660 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7661 { # Linux, FreeBSD
7662 next;
7663 }
7664 }
7665 if(not $Dep)
7666 { # nothing to include
7667 next;
7668 }
7669 if(is_default_include_dir($Dep))
7670 { # included by the compiler
7671 next;
7672 }
7673 if(get_depth($Dep)==1)
7674 { # too short
7675 next;
7676 }
7677 if(isLibcDir($Dep))
7678 { # do NOT include /usr/include/{sys,bits}
7679 next;
7680 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007681 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007682 }
7683 }
7684 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7685 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7686}
7687
7688sub sortIncPaths($$)
7689{
7690 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007691 if(not $ArrRef or $#{$ArrRef}<0) {
7692 return $ArrRef;
7693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007694 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7695 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007696 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007697 return $ArrRef;
7698}
7699
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007700sub sortDeps($$$)
7701{
7702 if($Header_Dependency{$_[2]}{$_[0]}
7703 and not $Header_Dependency{$_[2]}{$_[1]}) {
7704 return 1;
7705 }
7706 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7707 and $Header_Dependency{$_[2]}{$_[1]}) {
7708 return -1;
7709 }
7710 return 0;
7711}
7712
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007713sub join_P($$)
7714{
7715 my $S = "/";
7716 if($OSgroup eq "windows") {
7717 $S = "\\";
7718 }
7719 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007720}
7721
7722sub get_namespace_additions($)
7723{
7724 my $NameSpaces = $_[0];
7725 my ($Additions, $AddNameSpaceId) = ("", 1);
7726 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7727 {
7728 next if($SkipNameSpaces{$Version}{$NS});
7729 next if(not $NS or $NameSpaces->{$NS}==-1);
7730 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7731 next if($NS=~/\A__/i);
7732 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007733 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007734 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7735 my @NS_Parts = split(/::/, $NS);
7736 next if($#NS_Parts==-1);
7737 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7738 foreach my $NS_Part (@NS_Parts)
7739 {
7740 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7741 $TypeDecl_Suffix .= "}";
7742 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007743 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007744 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7745 $Additions.=" $TypeDecl\n $FuncDecl\n";
7746 $AddNameSpaceId+=1;
7747 }
7748 return $Additions;
7749}
7750
7751sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007752{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007753 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007754 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007755 if($Fmt eq "windows")
7756 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007757 $Path=~s/\//\\/g;
7758 $Path=lc($Path);
7759 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007760 else
7761 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007762 $Path=~s/\\/\//g;
7763 }
7764 return $Path;
7765}
7766
7767sub inc_opt($$)
7768{
7769 my ($Path, $Style) = @_;
7770 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007771 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007772 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007773 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007774 return "-I\"".path_format($Path, "unix")."\"";
7775 }
7776 elsif($OSgroup eq "macos"
7777 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007778 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007779 return "-F".esc(get_dirname($Path));
7780 }
7781 else {
7782 return "-I".esc($Path);
7783 }
7784 }
7785 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007786 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007787 }
7788 return "";
7789}
7790
7791sub platformSpecs($)
7792{
7793 my $LibVersion = $_[0];
7794 my $Arch = getArch($LibVersion);
7795 if($OStarget eq "symbian")
7796 { # options for GCCE compiler
7797 my %Symbian_Opts = map {$_=>1} (
7798 "-D__GCCE__",
7799 "-DUNICODE",
7800 "-fexceptions",
7801 "-D__SYMBIAN32__",
7802 "-D__MARM_INTERWORK__",
7803 "-D_UNICODE",
7804 "-D__S60_50__",
7805 "-D__S60_3X__",
7806 "-D__SERIES60_3X__",
7807 "-D__EPOC32__",
7808 "-D__MARM__",
7809 "-D__EABI__",
7810 "-D__MARM_ARMV5__",
7811 "-D__SUPPORT_CPP_EXCEPTIONS__",
7812 "-march=armv5t",
7813 "-mapcs",
7814 "-mthumb-interwork",
7815 "-DEKA2",
7816 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7817 );
7818 return join(" ", keys(%Symbian_Opts));
7819 }
7820 elsif($OSgroup eq "windows"
7821 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7822 { # add options to MinGW compiler
7823 # to simulate the MSVC compiler
7824 my %MinGW_Opts = map {$_=>1} (
7825 "-D_WIN32",
7826 "-D_STDCALL_SUPPORTED",
7827 "-D__int64=\"long long\"",
7828 "-D__int32=int",
7829 "-D__int16=short",
7830 "-D__int8=char",
7831 "-D__possibly_notnullterminated=\" \"",
7832 "-D__nullterminated=\" \"",
7833 "-D__nullnullterminated=\" \"",
7834 "-D__w64=\" \"",
7835 "-D__ptr32=\" \"",
7836 "-D__ptr64=\" \"",
7837 "-D__forceinline=inline",
7838 "-D__inline=inline",
7839 "-D__uuidof(x)=IID()",
7840 "-D__try=",
7841 "-D__except(x)=",
7842 "-D__declspec(x)=__attribute__((x))",
7843 "-D__pragma(x)=",
7844 "-D_inline=inline",
7845 "-D__forceinline=__inline",
7846 "-D__stdcall=__attribute__((__stdcall__))",
7847 "-D__cdecl=__attribute__((__cdecl__))",
7848 "-D__fastcall=__attribute__((__fastcall__))",
7849 "-D__thiscall=__attribute__((__thiscall__))",
7850 "-D_stdcall=__attribute__((__stdcall__))",
7851 "-D_cdecl=__attribute__((__cdecl__))",
7852 "-D_fastcall=__attribute__((__fastcall__))",
7853 "-D_thiscall=__attribute__((__thiscall__))",
7854 "-DSHSTDAPI_(x)=x",
7855 "-D_MSC_EXTENSIONS",
7856 "-DSECURITY_WIN32",
7857 "-D_MSC_VER=1500",
7858 "-D_USE_DECLSPECS_FOR_SAL",
7859 "-D__noop=\" \"",
7860 "-DDECLSPEC_DEPRECATED=\" \"",
7861 "-D__builtin_alignof(x)=__alignof__(x)",
7862 "-DSORTPP_PASS");
7863 if($Arch eq "x86") {
7864 $MinGW_Opts{"-D_M_IX86=300"}=1;
7865 }
7866 elsif($Arch eq "x86_64") {
7867 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7868 }
7869 elsif($Arch eq "ia64") {
7870 $MinGW_Opts{"-D_M_IA64=300"}=1;
7871 }
7872 return join(" ", keys(%MinGW_Opts));
7873 }
7874 return "";
7875}
7876
7877my %C_Structure = map {$_=>1} (
7878# FIXME: Can't separate union and struct data types before dumping,
7879# so it sometimes cause compilation errors for unknown reason
7880# when trying to declare TYPE* tmp_add_class_N
7881# This is a list of such structures + list of other C structures
7882 "sigval",
7883 "sigevent",
7884 "sigaction",
7885 "sigvec",
7886 "sigstack",
7887 "timeval",
7888 "timezone",
7889 "rusage",
7890 "rlimit",
7891 "wait",
7892 "flock",
7893 "stat",
7894 "_stat",
7895 "stat32",
7896 "_stat32",
7897 "stat64",
7898 "_stat64",
7899 "_stati64",
7900 "if_nameindex",
7901 "usb_device",
7902 "sigaltstack",
7903 "sysinfo",
7904 "timeLocale",
7905 "tcp_debug",
7906 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007907 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007908 "timespec",
7909 "random_data",
7910 "drand48_data",
7911 "_IO_marker",
7912 "_IO_FILE",
7913 "lconv",
7914 "sched_param",
7915 "tm",
7916 "itimerspec",
7917 "_pthread_cleanup_buffer",
7918 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007919 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007920 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007921 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007922 "sigcontext",
7923 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007924 # Mac
7925 "_timex",
7926 "_class_t",
7927 "_category_t",
7928 "_class_ro_t",
7929 "_protocol_t",
7930 "_message_ref_t",
7931 "_super_message_ref_t",
7932 "_ivar_t",
7933 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007934);
7935
7936sub getCompileCmd($$$)
7937{
7938 my ($Path, $Opt, $Inc) = @_;
7939 my $GccCall = $GCC_PATH;
7940 if($Opt) {
7941 $GccCall .= " ".$Opt;
7942 }
7943 $GccCall .= " -x ";
7944 if($OSgroup eq "macos") {
7945 $GccCall .= "objective-";
7946 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007947
7948 if($EMERGENCY_MODE_48)
7949 { # workaround for GCC 4.8 (C only)
7950 $GccCall .= "c++";
7951 }
7952 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007953 { # compile as "C++" header
7954 # to obtain complete dump using GCC 4.0
7955 $GccCall .= "c++-header";
7956 }
7957 else
7958 { # compile as "C++" source
7959 # GCC 3.3 cannot compile headers
7960 $GccCall .= "c++";
7961 }
7962 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007963 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007964 $GccCall .= " ".$Opts;
7965 }
7966 # allow extra qualifications
7967 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007968 $GccCall .= " -fpermissive";
7969 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007970 if($NoStdInc)
7971 {
7972 $GccCall .= " -nostdinc";
7973 $GccCall .= " -nostdinc++";
7974 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007975 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007976 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007977 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007978 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007979 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007980 if($Inc)
7981 { # include paths
7982 $GccCall .= " ".$Inc;
7983 }
7984 return $GccCall;
7985}
7986
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007987sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007988{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007989 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007990 my %HeaderElems = (
7991 # Types
7992 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007993 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007994 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
7995 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007996 "time.h" => ["time_t"],
7997 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007998 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
7999 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008000 "stdbool.h" => ["_Bool"],
8001 "rpc/xdr.h" => ["bool_t"],
8002 "in_systm.h" => ["n_long", "n_short"],
8003 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008004 "arpa/inet.h" => ["fw_src", "ip_src"],
8005 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008006 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008007 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008008 );
8009 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008010 foreach (keys(%HeaderElems))
8011 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008012 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008013 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008014 }
8015 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008016 my %Types = ();
8017 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8018 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008019 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008020 }
8021 if(keys(%Types))
8022 {
8023 my %AddHeaders = ();
8024 foreach my $Type (keys(%Types))
8025 {
8026 if(my $Header = $AutoPreamble{$Type})
8027 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008028 if(my $Path = identifyHeader($Header, $LibVersion))
8029 {
8030 if(skipHeader($Path, $LibVersion)) {
8031 next;
8032 }
8033 $Path = path_format($Path, $OSgroup);
8034 $AddHeaders{$Path}{"Type"} = $Type;
8035 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008036 }
8037 }
8038 }
8039 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008040 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008041 }
8042 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008043 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008044}
8045
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008046sub checkCTags($)
8047{
8048 my $Path = $_[0];
8049 if(not $Path) {
8050 return;
8051 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008052 my $CTags = undef;
8053
8054 if($OSgroup eq "bsd")
8055 { # use ectags on BSD
8056 $CTags = get_CmdPath("ectags");
8057 if(not $CTags) {
8058 printMsg("WARNING", "can't find \'ectags\' program");
8059 }
8060 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008061 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008062 $CTags = get_CmdPath("ctags");
8063 }
8064 if(not $CTags)
8065 {
8066 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008067 return;
8068 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008069
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008070 if($OSgroup ne "linux")
8071 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008072 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8073 if($Info!~/exuberant/i)
8074 {
8075 printMsg("WARNING", "incompatible version of \'ctags\' program");
8076 return;
8077 }
8078 }
8079
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008080 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008081 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008082 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008083 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008084 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008085 open(CTAGS, "<", $Out);
8086 while(my $Line = <CTAGS>)
8087 {
8088 chomp($Line);
8089 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008090 if(defined $Intrinsic_Keywords{$Name})
8091 { # noise
8092 next;
8093 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008094 if($Type eq "n")
8095 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008096 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008097 next;
8098 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008099 if(index($Scpe, "struct:")==0) {
8100 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008101 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008102 if(index($Scpe, "namespace:")==0)
8103 {
8104 if($Scpe=~s/\Anamespace://) {
8105 $Name = $Scpe."::".$Name;
8106 }
8107 }
8108 $TUnit_NameSpaces{$Version}{$Name} = 1;
8109 }
8110 elsif($Type eq "p")
8111 {
8112 if(not $Scpe or index($Scpe, "namespace:")==0) {
8113 $TUnit_Funcs{$Version}{$Name} = 1;
8114 }
8115 }
8116 elsif($Type eq "x")
8117 {
8118 if(not $Scpe or index($Scpe, "namespace:")==0) {
8119 $TUnit_Vars{$Version}{$Name} = 1;
8120 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008121 }
8122 }
8123 close(CTAGS);
8124}
8125
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008126sub preChange($$)
8127{
8128 my ($HeaderPath, $IncStr) = @_;
8129
8130 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8131 my $Content = undef;
8132
8133 if($OStarget eq "windows"
8134 and get_dumpmachine($GCC_PATH)=~/mingw/i
8135 and $MinGWMode{$Version}!=-1)
8136 { # modify headers to compile by MinGW
8137 if(not $Content)
8138 { # preprocessing
8139 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8140 }
8141 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8142 { # __asm { ... }
8143 $MinGWMode{$Version}=1;
8144 }
8145 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8146 { # comments after preprocessing
8147 $MinGWMode{$Version}=1;
8148 }
8149 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8150 { # 0xffui8
8151 $MinGWMode{$Version}=1;
8152 }
8153
8154 if($MinGWMode{$Version}) {
8155 printMsg("INFO", "Using MinGW compatibility mode");
8156 }
8157 }
8158
8159 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8160 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8161 { # rename C++ keywords in C code
8162 # disable this code by -cpp-compatible option
8163 if(not $Content)
8164 { # preprocessing
8165 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8166 }
8167 my $RegExp_C = join("|", keys(%CppKeywords_C));
8168 my $RegExp_F = join("|", keys(%CppKeywords_F));
8169 my $RegExp_O = join("|", keys(%CppKeywords_O));
8170
8171 my $Detected = undef;
8172
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008173 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 +04008174 { # MATCH:
8175 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008176 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008177 # unsigned private: 8;
8178 # DO NOT MATCH:
8179 # #pragma GCC visibility push(default)
8180 $CppMode{$Version} = 1;
8181 $Detected = "$1$2$3$4" if(not defined $Detected);
8182 }
8183 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8184 { # MATCH:
8185 # int delete(...);
8186 # int explicit(...);
8187 # DO NOT MATCH:
8188 # void operator delete(...)
8189 $CppMode{$Version} = 1;
8190 $Detected = "$1$2$3" if(not defined $Detected);
8191 }
8192 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8193 { # MATCH:
8194 # int bool;
8195 # DO NOT MATCH:
8196 # bool X;
8197 # return *this;
8198 # throw;
8199 $CppMode{$Version} = 1;
8200 $Detected = "$1$2$3" if(not defined $Detected);
8201 }
8202 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8203 { # MATCH:
8204 # int operator(...);
8205 # DO NOT MATCH:
8206 # int operator()(...);
8207 $CppMode{$Version} = 1;
8208 $Detected = "$1$2$3" if(not defined $Detected);
8209 }
8210 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8211 { # MATCH:
8212 # int foo(int operator);
8213 # int foo(int operator, int other);
8214 # DO NOT MATCH:
8215 # int operator,(...);
8216 $CppMode{$Version} = 1;
8217 $Detected = "$1$2$3" if(not defined $Detected);
8218 }
8219 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8220 { # MATCH:
8221 # int foo(gboolean *bool);
8222 # DO NOT MATCH:
8223 # void setTabEnabled(int index, bool);
8224 $CppMode{$Version} = 1;
8225 $Detected = "$1$2$3" if(not defined $Detected);
8226 }
8227 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8228 { # MATCH:
8229 # int foo(int* this);
8230 # int bar(int this);
8231 # int baz(int throw);
8232 # DO NOT MATCH:
8233 # foo(X, this);
8234 $CppMode{$Version} = 1;
8235 $Detected = "$1$2$3$4" if(not defined $Detected);
8236 }
8237 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8238 { # MATCH:
8239 # struct template {...};
8240 # extern template foo(...);
8241 $CppMode{$Version} = 1;
8242 $Detected = "$1$2" if(not defined $Detected);
8243 }
8244
8245 if($CppMode{$Version} == 1)
8246 {
8247 if($Debug)
8248 {
8249 $Detected=~s/\A\s+//g;
8250 printMsg("INFO", "Detected code: \"$Detected\"");
8251 }
8252 }
8253
8254 # remove typedef enum NAME NAME;
8255 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8256 my $N = 0;
8257 while($N<=$#FwdTypedefs-1)
8258 {
8259 my $S = $FwdTypedefs[$N];
8260 if($S eq $FwdTypedefs[$N+1])
8261 {
8262 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008263 $CppMode{$Version} = 1;
8264
8265 if($Debug) {
8266 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8267 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008268 }
8269 $N+=2;
8270 }
8271
8272 if($CppMode{$Version}==1) {
8273 printMsg("INFO", "Using C++ compatibility mode");
8274 }
8275 }
8276
8277 if($CppMode{$Version}==1
8278 or $MinGWMode{$Version}==1)
8279 {
8280 my $IPath = $TMP_DIR."/dump$Version.i";
8281 writeFile($IPath, $Content);
8282 return $IPath;
8283 }
8284
8285 return undef;
8286}
8287
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008288sub getDump()
8289{
8290 if(not $GCC_PATH) {
8291 exitStatus("Error", "internal error - GCC path is not set");
8292 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008293
8294 my @Headers = keys(%{$Registered_Headers{$Version}});
8295 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8296
8297 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8298
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008299 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008300 my $HeaderPath = $TmpHeaderPath;
8301
8302 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008303 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008304 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8305 {
8306 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008307 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008308 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008309 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008310 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8311 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008312 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008313 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008314 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008315 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8316 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8317 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008318 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008319 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008320
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008321 if($ExtraInfo)
8322 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008323 if($IncludeString) {
8324 writeFile($ExtraInfo."/include-string", $IncludeString);
8325 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008326 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8327 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008328
8329 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8330 {
8331 my $REDIR = "";
8332 foreach my $P1 (sort @Redirects) {
8333 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8334 }
8335 writeFile($ExtraInfo."/include-redirect", $REDIR);
8336 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008337 }
8338
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008339 if(not keys(%{$TargetHeaders{$Version}}))
8340 { # Target headers
8341 addTargetHeaders($Version);
8342 }
8343
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008344 # clean memory
8345 %RecursiveIncludes = ();
8346 %Header_Include_Prefix = ();
8347 %Header_Includes = ();
8348
8349 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008350 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008351 delete($Cache{"detect_header_includes"});
8352 delete($Cache{"selectSystemHeader"});
8353
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008354 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008355 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8356 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008357
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008358 if($ExtraInfo)
8359 { # extra information for other tools
8360 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8361 }
8362
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008363 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008364 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008365 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008366
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008367 if($COMMON_LANGUAGE{$Version} eq "C++") {
8368 checkCTags($Pre);
8369 }
8370
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008371 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8372 { # try to correct the preprocessor output
8373 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008374 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008375
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008376 if($COMMON_LANGUAGE{$Version} eq "C++")
8377 { # add classes and namespaces to the dump
8378 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008379 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008380 or $MinGWMode{$Version}==1) {
8381 $CHdump .= " -fpreprocessed";
8382 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008383 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008384 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008385 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008386 chdir($ORIG_DIR);
8387 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8388 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008389 my $Content = readFile($ClassDump);
8390 foreach my $ClassInfo (split(/\n\n/, $Content))
8391 {
8392 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8393 {
8394 my $CName = $1;
8395 next if($CName=~/\A(__|_objc_|_opaque_)/);
8396 $TUnit_NameSpaces{$Version}{$CName} = -1;
8397 if($CName=~/\A[\w:]+\Z/)
8398 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008399 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008400 }
8401 if($CName=~/(\w[\w:]*)::/)
8402 { # namespaces
8403 my $NS = $1;
8404 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8405 $TUnit_NameSpaces{$Version}{$NS} = 1;
8406 }
8407 }
8408 }
8409 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8410 { # read v-tables (advanced approach)
8411 my ($CName, $VTable) = ($1, $2);
8412 $ClassVTable_Content{$Version}{$CName} = $VTable;
8413 }
8414 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008415 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8416 { # add user-defined namespaces
8417 $TUnit_NameSpaces{$Version}{$NS} = 1;
8418 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008419 if($Debug)
8420 { # debug mode
8421 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008422 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008423 }
8424 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008425 }
8426
8427 # add namespaces and classes
8428 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8429 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008430 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008431 }
8432 # some GCC versions don't include class methods to the TU dump by default
8433 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008434 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008435 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8436 {
8437 next if($C_Structure{$CName});
8438 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008439 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008440 if(not $Force and $GCC_44
8441 and $OSgroup eq "linux")
8442 { # optimization for linux with GCC >= 4.4
8443 # disable this code by -force option
8444 if(index($CName, "::")!=-1)
8445 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008446 next;
8447 }
8448 }
8449 else
8450 {
8451 if($CName=~/\A(.+)::[^:]+\Z/
8452 and $TUnit_Classes{$Version}{$1})
8453 { # classes inside other classes
8454 next;
8455 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008456 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008457 if(defined $TUnit_Funcs{$Version}{$CName})
8458 { # the same name for a function and type
8459 next;
8460 }
8461 if(defined $TUnit_Vars{$Version}{$CName})
8462 { # the same name for a variable and type
8463 next;
8464 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008465 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8466 }
8467 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008468 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008469 }
8470 }
8471 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8472 # create TU dump
8473 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008474 if($UserLang eq "C") {
8475 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8476 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008477 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008478 or $MinGWMode{$Version}==1) {
8479 $TUdump .= " -fpreprocessed";
8480 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008481 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008482 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8483 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008484 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008485 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008486 if($?)
8487 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008488 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008489 { # try to recompile
8490 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008491 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008492 and index($Errors, "c99_")!=-1
8493 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008494 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008495 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008496
8497 if($Debug)
8498 {
8499 # printMsg("INFO", $Errors);
8500 }
8501
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008502 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008503 resetLogging($Version);
8504 $TMP_DIR = tempdir(CLEANUP=>1);
8505 return getDump();
8506 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008507 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008508 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008509 { # add auto preamble headers and try again
8510 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008511 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008512 foreach my $Num (0 .. $#Headers)
8513 {
8514 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008515 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8516 {
8517 push_U($Include_Preamble{$Version}, $Path);
8518 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008519 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008520 }
8521 resetLogging($Version);
8522 $TMP_DIR = tempdir(CLEANUP=>1);
8523 return getDump();
8524 }
8525 elsif($Cpp0xMode{$Version}!=-1
8526 and ($Errors=~/\Q-std=c++0x\E/
8527 or $Errors=~/is not a class or namespace/))
8528 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008529 if(check_gcc($GCC_PATH, "4.6"))
8530 {
8531 $Cpp0xMode{$Version}=-1;
8532 printMsg("INFO", "Enabling c++0x mode");
8533 resetLogging($Version);
8534 $TMP_DIR = tempdir(CLEANUP=>1);
8535 $CompilerOptions{$Version} .= " -std=c++0x";
8536 return getDump();
8537 }
8538 else {
8539 printMsg("WARNING", "Probably c++0x construction detected");
8540 }
8541
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008542 }
8543 elsif($MinGWMode{$Version}==1)
8544 { # disable MinGW mode and try again
8545 $MinGWMode{$Version}=-1;
8546 resetLogging($Version);
8547 $TMP_DIR = tempdir(CLEANUP=>1);
8548 return getDump();
8549 }
8550 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008551 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008552 else {
8553 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008554 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008555 printMsg("ERROR", "some errors occurred when compiling headers");
8556 printErrorLog($Version);
8557 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008558 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008559 }
8560 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008561 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008562 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008563
8564 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8565 return $TUs[0];
8566 }
8567 else
8568 {
8569 my $Msg = "can't compile header(s)";
8570 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8571 $Msg .= "\nDid you install G++?";
8572 }
8573 exitStatus("Cannot_Compile", $Msg);
8574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008575}
8576
8577sub cmd_file($)
8578{
8579 my $Path = $_[0];
8580 return "" if(not $Path or not -e $Path);
8581 if(my $CmdPath = get_CmdPath("file")) {
8582 return `$CmdPath -b \"$Path\"`;
8583 }
8584 return "";
8585}
8586
8587sub getIncString($$)
8588{
8589 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008590 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008591 my $String = "";
8592 foreach (@{$ArrRef}) {
8593 $String .= " ".inc_opt($_, $Style);
8594 }
8595 return $String;
8596}
8597
8598sub getIncPaths(@)
8599{
8600 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008601 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008602 if($INC_PATH_AUTODETECT{$Version})
8603 { # auto-detecting dependencies
8604 my %Includes = ();
8605 foreach my $HPath (@HeaderPaths)
8606 {
8607 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8608 {
8609 if($Skip_Include_Paths{$Version}{$Dir}) {
8610 next;
8611 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008612 if($SystemRoot)
8613 {
8614 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8615 next;
8616 }
8617 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008618 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008619 }
8620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008621 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008622 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008623 }
8624 }
8625 else
8626 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008627 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008628 }
8629 return \@IncPaths;
8630}
8631
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008632sub push_U($@)
8633{ # push unique
8634 if(my $Array = shift @_)
8635 {
8636 if(@_)
8637 {
8638 my %Exist = map {$_=>1} @{$Array};
8639 foreach my $Elem (@_)
8640 {
8641 if(not defined $Exist{$Elem})
8642 {
8643 push(@{$Array}, $Elem);
8644 $Exist{$Elem} = 1;
8645 }
8646 }
8647 }
8648 }
8649}
8650
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008651sub callPreprocessor($$$)
8652{
8653 my ($Path, $Inc, $LibVersion) = @_;
8654 return "" if(not $Path or not -f $Path);
8655 my $IncludeString=$Inc;
8656 if(not $Inc) {
8657 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8658 }
8659 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008660 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008661 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008662 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008663}
8664
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008665sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008666{ # native "find" is much faster than File::Find (~6x)
8667 # also the File::Find doesn't support --maxdepth N option
8668 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008669 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008670 return () if(not $Path or not -e $Path);
8671 if($OSgroup eq "windows")
8672 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008673 $Path = get_abs_path($Path);
8674 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008675 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008676 if($MaxDepth!=1) {
8677 $Cmd .= " /S";
8678 }
8679 if($Type eq "d") {
8680 $Cmd .= " /AD";
8681 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008682 elsif($Type eq "f") {
8683 $Cmd .= " /A-D";
8684 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008685 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008686 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008687 {
8688 if(not $UseRegex)
8689 { # FIXME: how to search file names in MS shell?
8690 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008691 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008692 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008693 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008694 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008695 }
8696 my @AbsPaths = ();
8697 foreach my $File (@Files)
8698 {
8699 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008700 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008701 }
8702 if($Type eq "f" and not -f $File)
8703 { # skip dirs
8704 next;
8705 }
8706 push(@AbsPaths, path_format($File, $OSgroup));
8707 }
8708 if($Type eq "d") {
8709 push(@AbsPaths, $Path);
8710 }
8711 return @AbsPaths;
8712 }
8713 else
8714 {
8715 my $FindCmd = get_CmdPath("find");
8716 if(not $FindCmd) {
8717 exitStatus("Not_Found", "can't find a \"find\" command");
8718 }
8719 $Path = get_abs_path($Path);
8720 if(-d $Path and -l $Path
8721 and $Path!~/\/\Z/)
8722 { # for directories that are symlinks
8723 $Path.="/";
8724 }
8725 my $Cmd = $FindCmd." \"$Path\"";
8726 if($MaxDepth) {
8727 $Cmd .= " -maxdepth $MaxDepth";
8728 }
8729 if($Type) {
8730 $Cmd .= " -type $Type";
8731 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008732 if($Name and not $UseRegex)
8733 { # wildcards
8734 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008735 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008736 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008737 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008738 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8739 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008740 my @Files = split(/\n/, $Res);
8741 if($Name and $UseRegex)
8742 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008743 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008744 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008745 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008746 }
8747}
8748
8749sub unpackDump($)
8750{
8751 my $Path = $_[0];
8752 return "" if(not $Path or not -e $Path);
8753 $Path = get_abs_path($Path);
8754 $Path = path_format($Path, $OSgroup);
8755 my ($Dir, $FileName) = separate_path($Path);
8756 my $UnpackDir = $TMP_DIR."/unpack";
8757 rmtree($UnpackDir);
8758 mkpath($UnpackDir);
8759 if($FileName=~s/\Q.zip\E\Z//g)
8760 { # *.zip
8761 my $UnzipCmd = get_CmdPath("unzip");
8762 if(not $UnzipCmd) {
8763 exitStatus("Not_Found", "can't find \"unzip\" command");
8764 }
8765 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008766 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008767 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008768 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008769 }
8770 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008771 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008772 if(not @Contents) {
8773 exitStatus("Error", "can't extract \'$Path\'");
8774 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008775 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008776 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008777 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008778 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008779 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008780 if($OSgroup eq "windows")
8781 { # -xvzf option is not implemented in tar.exe (2003)
8782 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8783 my $TarCmd = get_CmdPath("tar");
8784 if(not $TarCmd) {
8785 exitStatus("Not_Found", "can't find \"tar\" command");
8786 }
8787 my $GzipCmd = get_CmdPath("gzip");
8788 if(not $GzipCmd) {
8789 exitStatus("Not_Found", "can't find \"gzip\" command");
8790 }
8791 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008792 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008793 if($?) {
8794 exitStatus("Error", "can't extract \'$Path\'");
8795 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008796 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008797 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008798 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008799 }
8800 chdir($ORIG_DIR);
8801 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008802 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008803 if(not @Contents) {
8804 exitStatus("Error", "can't extract \'$Path\'");
8805 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008806 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008807 }
8808 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008809 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008810 my $TarCmd = get_CmdPath("tar");
8811 if(not $TarCmd) {
8812 exitStatus("Not_Found", "can't find \"tar\" command");
8813 }
8814 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008815 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008816 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008817 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008818 }
8819 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008820 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008821 if(not @Contents) {
8822 exitStatus("Error", "can't extract \'$Path\'");
8823 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008824 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008825 }
8826 }
8827}
8828
8829sub createArchive($$)
8830{
8831 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008832 if(not $To) {
8833 $To = ".";
8834 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008835 if(not $Path or not -e $Path
8836 or not -d $To) {
8837 return "";
8838 }
8839 my ($From, $Name) = separate_path($Path);
8840 if($OSgroup eq "windows")
8841 { # *.zip
8842 my $ZipCmd = get_CmdPath("zip");
8843 if(not $ZipCmd) {
8844 exitStatus("Not_Found", "can't find \"zip\"");
8845 }
8846 my $Pkg = $To."/".$Name.".zip";
8847 unlink($Pkg);
8848 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008849 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008850 if($?)
8851 { # cannot allocate memory (or other problems with "zip")
8852 unlink($Path);
8853 exitStatus("Error", "can't pack the ABI dump: ".$!);
8854 }
8855 chdir($ORIG_DIR);
8856 unlink($Path);
8857 return $Pkg;
8858 }
8859 else
8860 { # *.tar.gz
8861 my $TarCmd = get_CmdPath("tar");
8862 if(not $TarCmd) {
8863 exitStatus("Not_Found", "can't find \"tar\"");
8864 }
8865 my $GzipCmd = get_CmdPath("gzip");
8866 if(not $GzipCmd) {
8867 exitStatus("Not_Found", "can't find \"gzip\"");
8868 }
8869 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8870 unlink($Pkg);
8871 chdir($From);
8872 system($TarCmd, "-czf", $Pkg, $Name);
8873 if($?)
8874 { # cannot allocate memory (or other problems with "tar")
8875 unlink($Path);
8876 exitStatus("Error", "can't pack the ABI dump: ".$!);
8877 }
8878 chdir($ORIG_DIR);
8879 unlink($Path);
8880 return $To."/".$Name.".tar.gz";
8881 }
8882}
8883
8884sub is_header_file($)
8885{
8886 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8887 return $_[0];
8888 }
8889 return 0;
8890}
8891
8892sub is_not_header($)
8893{
8894 if($_[0]=~/\.\w+\Z/
8895 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8896 return 1;
8897 }
8898 return 0;
8899}
8900
8901sub is_header($$$)
8902{
8903 my ($Header, $UserDefined, $LibVersion) = @_;
8904 return 0 if(-d $Header);
8905 if(-f $Header) {
8906 $Header = get_abs_path($Header);
8907 }
8908 else
8909 {
8910 if(is_abs($Header))
8911 { # incorrect absolute path
8912 return 0;
8913 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008914 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008915 $Header = $HPath;
8916 }
8917 else
8918 { # can't find header
8919 return 0;
8920 }
8921 }
8922 if($Header=~/\.\w+\Z/)
8923 { # have an extension
8924 return is_header_file($Header);
8925 }
8926 else
8927 {
8928 if($UserDefined==2)
8929 { # specified on the command line
8930 if(cmd_file($Header)!~/HTML|XML/i) {
8931 return $Header;
8932 }
8933 }
8934 elsif($UserDefined)
8935 { # specified in the XML-descriptor
8936 # header file without an extension
8937 return $Header;
8938 }
8939 else
8940 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008941 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008942 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008943 { # !~/HTML|XML|shared|dynamic/i
8944 return $Header;
8945 }
8946 }
8947 }
8948 return 0;
8949}
8950
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008951sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008952{
8953 my $LibVersion = $_[0];
8954 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8955 {
8956 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008957 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008958
8959 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
8960 detect_recursive_includes($RegHeader, $LibVersion);
8961 }
8962
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008963 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
8964 {
8965 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008966
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04008967 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008968 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
8969 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008970 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008971 }
8972 }
8973 }
8974}
8975
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008976sub familiarDirs($$)
8977{
8978 my ($D1, $D2) = @_;
8979 if($D1 eq $D2) {
8980 return 1;
8981 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04008982
8983 my $U1 = index($D1, "/usr/");
8984 my $U2 = index($D2, "/usr/");
8985
8986 if($U1==0 and $U2!=0) {
8987 return 0;
8988 }
8989
8990 if($U2==0 and $U1!=0) {
8991 return 0;
8992 }
8993
8994 if(index($D2, $D1."/")==0) {
8995 return 1;
8996 }
8997
8998 # /usr/include/DIR
8999 # /home/user/DIR
9000
9001 my $DL = get_depth($D1);
9002
9003 my @Dirs1 = ($D1);
9004 while($DL - get_depth($D1)<=2
9005 and get_depth($D1)>=4
9006 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9007 push(@Dirs1, $D1);
9008 }
9009
9010 my @Dirs2 = ($D2);
9011 while(get_depth($D2)>=4
9012 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9013 push(@Dirs2, $D2);
9014 }
9015
9016 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009017 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009018 foreach my $P2 (@Dirs2)
9019 {
9020
9021 if($P1 eq $P2) {
9022 return 1;
9023 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009024 }
9025 }
9026 return 0;
9027}
9028
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009029sub readHeaders($)
9030{
9031 $Version = $_[0];
9032 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9033 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009034 if($Debug)
9035 { # debug mode
9036 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009037 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009038 }
9039 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009040}
9041
9042sub prepareTypes($)
9043{
9044 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009045 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009046 { # support for old ABI dumps
9047 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009048 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009049 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009050 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9051 if($TName=~/\A(\w+)::(\w+)/) {
9052 my ($P1, $P2) = ($1, $2);
9053 if($P1 eq $P2) {
9054 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009055 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009056 else {
9057 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9058 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009059 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009060 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009061 }
9062 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009063 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009064 { # support for old ABI dumps
9065 # V < 2.5: array size == "number of elements"
9066 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009067 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009068 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009069 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009070 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009071 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009072 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009073 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009074 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009075 $Size *= $Base{"Size"};
9076 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009077 }
9078 else
9079 { # array[] is a pointer
9080 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009081 }
9082 }
9083 }
9084 }
9085 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009086 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009087 { # support for old ABI dumps
9088 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009089 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009090 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009091 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009092 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009093 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009094 my %Type = get_Type($TypeId, $LibVersion);
9095 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9096 my %Type2 = get_Type($TypeId_2, $V2);
9097 if($Type{"Size"} ne $Type2{"Size"}) {
9098 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009099 }
9100 }
9101 }
9102 }
9103}
9104
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009105sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009106{
9107 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009108
9109 if(not keys(%{$SymbolInfo{$LibVersion}}))
9110 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009111 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009112 {
9113 if($CheckHeadersOnly) {
9114 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9115 }
9116 else {
9117 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9118 }
9119 }
9120 }
9121
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009122 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009123 if(not checkDump(1, "2.10")
9124 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009125 { # different formats
9126 $Remangle = 1;
9127 }
9128 if($CheckHeadersOnly)
9129 { # different languages
9130 if($UserLang)
9131 { # --lang=LANG for both versions
9132 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9133 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9134 {
9135 if($UserLang eq "C++")
9136 { # remangle symbols
9137 $Remangle = 1;
9138 }
9139 elsif($UserLang eq "C")
9140 { # remove mangling
9141 $Remangle = -1;
9142 }
9143 }
9144 }
9145 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009146
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009147 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009148 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009149 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009150 { # support for old ABI dumps
9151 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9152 {
9153 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9154 {
9155 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9156 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009157 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009158 if(defined $DVal and $DVal ne "")
9159 {
9160 if($TName eq "char") {
9161 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9162 }
9163 elsif($TName eq "bool") {
9164 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9165 }
9166 }
9167 }
9168 }
9169 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009170 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009171 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009172 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9173 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009174 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009175 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9176 # + support for old ABI dumps
9177 next;
9178 }
9179 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009180 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009181 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009182 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009183 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009184
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009185 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009186 if(not checkDump(1, "2.12")
9187 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009188 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009189 if($ShortName eq "operator>>")
9190 {
9191 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9192 { # corrected mangling of operator>>
9193 $SRemangle = 1;
9194 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009195 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009196 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9197 {
9198 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9199 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9200 { # corrected mangling of const global data
9201 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9202 # and incorrectly mangled by old ACC versions
9203 $SRemangle = 1;
9204 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009205 }
9206 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009207 if(not $CheckHeadersOnly)
9208 { # support for old ABI dumps
9209 if(not checkDump(1, "2.17")
9210 or not checkDump(2, "2.17"))
9211 {
9212 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9213 {
9214 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9215 {
9216 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9217 {
9218 $MnglName = $ShortName;
9219 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9220 }
9221 }
9222 }
9223 }
9224 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009225 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009226 { # support for old ABI dumps: some symbols are not mangled in old dumps
9227 # mangle both sets of symbols (old and new)
9228 # NOTE: remangling all symbols by the same mangler
9229 if($MnglName=~/\A_ZN(V|)K/)
9230 { # mangling may be incorrect on old ABI dumps
9231 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009232 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009233 }
9234 if($MnglName=~/\A_ZN(K|)V/)
9235 { # mangling may be incorrect on old ABI dumps
9236 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009237 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009238 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009239 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9240 or (not $ClassID and $CheckHeadersOnly)
9241 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9242 { # support for old ABI dumps, GCC >= 4.0
9243 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009244 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009245 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009246 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009247 $MangledNames{$LibVersion}{$MnglName} = 1;
9248 }
9249 }
9250 }
9251 elsif($Remangle==-1)
9252 { # remove mangling
9253 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009254 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009255 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009256 if(not $MnglName) {
9257 next;
9258 }
9259 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9260 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009261 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9262
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009263 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009264 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009265 { # support for old dumps
9266 # add "Volatile" attribute
9267 if($MnglName=~/_Z(K|)V/) {
9268 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9269 }
9270 }
9271 # symbol and its symlink have same signatures
9272 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009273 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009274 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009275
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009276 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9277 {
9278 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9279 if($SymVer{$LibVersion}{$Alias}) {
9280 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9281 }
9282 }
9283
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009284 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009285 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009286 }
9287 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9288 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9289 }
9290 if($ExtendedCheck)
9291 { # --ext option
9292 addExtension($LibVersion);
9293 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009294
9295 # clean memory
9296 delete($SymbolInfo{$LibVersion});
9297
9298 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009299 { # detect allocable classes with public exported constructors
9300 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009301 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009302 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009303 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009304 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009305 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9306 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009307 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009308 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009309 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009310 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009311 $AllocableClass{$LibVersion}{$ClassName} = 1;
9312 }
9313 }
9314 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009315 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009316 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009317 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009318 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009319 if($CheckHeadersOnly)
9320 {
9321 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9322 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9323 { # all symbols except non-virtual inline
9324 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9325 }
9326 }
9327 else {
9328 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009329 }
9330 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009331 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009332 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009333 }
9334 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009335 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009336 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009337 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009338 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009339 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009340 if(defined $Base{"Type"}
9341 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009342 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009343 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009344 if($Name=~/<([^<>\s]+)>/)
9345 {
9346 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9347 $ReturnedClass{$LibVersion}{$Tid} = 1;
9348 }
9349 }
9350 else {
9351 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9352 }
9353 }
9354 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009355 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009356 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009357 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009358 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009359 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009360 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009361 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009362 if($Base{"Type"}=~/Struct|Class/)
9363 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009364 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009365 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9366 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009367 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009368 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009369 }
9370 }
9371 }
9372 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009373
9374 # mapping {short name => symbols}
9375 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009376 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009377 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009378 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009379 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009380 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009381 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009382 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009383 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9384 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009385 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009386 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009387 }
9388 }
9389 }
9390 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009391
9392 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009393 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009394 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009395 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009396 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009397 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9398 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009399 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009400 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009401 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009402 $ClassNames{$LibVersion}{$TName} = 1;
9403 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009404 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009405 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9406 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009407 }
9408 }
9409 }
9410 }
9411 }
9412}
9413
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009414sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009415{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009416 my ($Tid, $LibVersion) = @_;
9417 if(not $Tid) {
9418 return $Tid;
9419 }
9420
9421 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9422 {
9423 if($TName_Tid{$LibVersion}{$Name}) {
9424 return $TName_Tid{$LibVersion}{$Name};
9425 }
9426 }
9427
9428 return $Tid;
9429}
9430
9431sub register_SymbolUsage($$$)
9432{
9433 my ($InfoId, $UsedType, $LibVersion) = @_;
9434
9435 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9436 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9437 {
9438 register_TypeUsage($RTid, $UsedType, $LibVersion);
9439 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9440 }
9441 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9442 {
9443 register_TypeUsage($FCid, $UsedType, $LibVersion);
9444 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9445
9446 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9447 { # register "this" pointer
9448 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9449 }
9450 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9451 { # register "this" pointer (const method)
9452 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9453 }
9454 }
9455 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9456 {
9457 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9458 {
9459 register_TypeUsage($PTid, $UsedType, $LibVersion);
9460 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9461 }
9462 }
9463 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9464 {
9465 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9466 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9467 register_TypeUsage($TTid, $UsedType, $LibVersion);
9468 }
9469 }
9470}
9471
9472sub register_TypeUsage($$$)
9473{
9474 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009475 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009476 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009477 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009478 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009479 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009480 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009481 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009482
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009483 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009484 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009485 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009486 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009487 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009488 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9489 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9490 }
9491 }
9492
9493 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9494 {
9495 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009496 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009497 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009498 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9499 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009500 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009501 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9502 {
9503 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9504 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009505 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009506 }
9507 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009508 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009509 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009510 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009511 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9512 {
9513 register_TypeUsage($MTid, $UsedType, $LibVersion);
9514 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009515 }
9516 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009517 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009518 or $TInfo{"Type"} eq "MethodPtr"
9519 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009520 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009521 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009522 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009523 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009524 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009525 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009526 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9527 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009528 }
9529 }
9530 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009531 if($TInfo{"Type"} eq "FieldPtr")
9532 {
9533 if(my $RTid = $TInfo{"Return"}) {
9534 register_TypeUsage($RTid, $UsedType, $LibVersion);
9535 }
9536 if(my $CTid = $TInfo{"Class"}) {
9537 register_TypeUsage($CTid, $UsedType, $LibVersion);
9538 }
9539 }
9540 if($TInfo{"Type"} eq "MethodPtr")
9541 {
9542 if(my $CTid = $TInfo{"Class"}) {
9543 register_TypeUsage($CTid, $UsedType, $LibVersion);
9544 }
9545 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009546 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009547 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009548 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009549 $UsedType->{$TypeId} = 1;
9550 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9551 {
9552 register_TypeUsage($BTid, $UsedType, $LibVersion);
9553 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9554 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009555 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009556 else
9557 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9558 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009559 }
9560 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009561}
9562
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009563sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009564{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009565 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9566
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009567 if($Level eq "Dump")
9568 {
9569 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9570 { # TODO: check if this symbol is from
9571 # base classes of other target symbols
9572 return 1;
9573 }
9574 }
9575
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009576 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9577 { # stdc++ interfaces
9578 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009579 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009580
9581 my $Target = 0;
9582 if(my $Header = $SInfo->{"Header"}) {
9583 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9584 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009585 if($ExtendedCheck)
9586 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009587 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009588 $Target = 1;
9589 }
9590 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009591 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009592 {
9593 if($Target)
9594 {
9595 if($Level eq "Dump")
9596 { # dumped
9597 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009598 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009599 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009600 return 1;
9601 }
9602 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009603 else {
9604 return 1;
9605 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009606 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009607 elsif($Level eq "Source")
9608 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009609 return 1;
9610 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009611 elsif($Level eq "Binary")
9612 { # checked
9613 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9614 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9615 return 1;
9616 }
9617 }
9618 }
9619 }
9620 else
9621 { # library is available
9622 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9623 { # exported symbols
9624 return 1;
9625 }
9626 if($Level eq "Dump")
9627 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009628 if($BinaryOnly)
9629 {
9630 if($SInfo->{"Data"})
9631 {
9632 if($Target) {
9633 return 1;
9634 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009635 }
9636 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009637 else
9638 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009639 if($Target) {
9640 return 1;
9641 }
9642 }
9643 }
9644 elsif($Level eq "Source")
9645 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009646 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009647 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009648 { # skip LOCAL symbols
9649 if($Target) {
9650 return 1;
9651 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009652 }
9653 }
9654 elsif($Level eq "Binary")
9655 { # checked
9656 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9657 {
9658 if($Target) {
9659 return 1;
9660 }
9661 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009662 }
9663 }
9664 return 0;
9665}
9666
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009667sub cleanDump($)
9668{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009669 my $LibVersion = $_[0];
9670 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9671 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009672 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9673 {
9674 delete($SymbolInfo{$LibVersion}{$InfoId});
9675 next;
9676 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009677 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009678 if(not $MnglName)
9679 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009680 delete($SymbolInfo{$LibVersion}{$InfoId});
9681 next;
9682 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009683 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009684 if(not $ShortName)
9685 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009686 delete($SymbolInfo{$LibVersion}{$InfoId});
9687 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009688 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009689 if($MnglName eq $ShortName)
9690 { # remove duplicate data
9691 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009692 }
9693 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9694 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9695 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009696 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9697 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9698 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009699 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009700 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009701 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009702 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009703 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9704 {
9705 delete($TypeInfo{$LibVersion}{$Tid});
9706 next;
9707 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009708 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009709 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009710 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009711 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9712 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9713 }
9714 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009715 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9716 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9717 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009718 }
9719}
9720
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009721sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009722{
9723 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009724
9725 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9726 {
9727 if(defined $TypeInfo{$LibVersion}{$Dupl})
9728 {
9729 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9730 { # duplicate
9731 return 0;
9732 }
9733 }
9734 }
9735
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009736 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9737
9738 if(isBuiltIn($THeader)) {
9739 return 0;
9740 }
9741
9742 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9743 return 0;
9744 }
9745
9746 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9747 return 0;
9748 }
9749
9750 if(selfTypedef($Tid, $LibVersion)) {
9751 return 0;
9752 }
9753
9754 if(not isTargetType($Tid, $LibVersion)) {
9755 return 0;
9756 }
9757
9758 return 0;
9759}
9760
9761sub isTargetType($$)
9762{
9763 my ($Tid, $LibVersion) = @_;
9764
9765 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9766 { # derived
9767 return 1;
9768 }
9769
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009770 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9771 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009772 if(not is_target_header($THeader, $LibVersion))
9773 { # from target headers
9774 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009775 }
9776 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009777
9778 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009779}
9780
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009781sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009782{ # remove unused data types from the ABI dump
9783 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009784
9785 my %UsedType = ();
9786
9787 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009788 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009789 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009790 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009791 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009792 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009793 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009794 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009795 next;
9796 }
9797
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009798 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009799 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009800 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009801 {
9802 my %Tree = ();
9803 register_TypeUsage($Tid, \%Tree, $LibVersion);
9804
9805 my $Tmpl = 0;
9806 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9807 {
9808 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9809 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9810 {
9811 $Tmpl = 1;
9812 last;
9813 }
9814 }
9815 if(not $Tmpl)
9816 {
9817 foreach (keys(%Tree)) {
9818 $UsedType{$_} = 1;
9819 }
9820 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009821 }
9822 }
9823 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009824
9825 my %Delete = ();
9826
9827 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009828 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009829 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009830 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009831 next;
9832 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009833
9834 if($Kind eq "Extra")
9835 {
9836 my %Tree = ();
9837 register_TypeUsage($Tid, \%Tree, $LibVersion);
9838
9839 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9840 {
9841 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9842 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9843 {
9844 $Delete{$Tid} = 1;
9845 last;
9846 }
9847 }
9848 }
9849 else
9850 {
9851 # remove type
9852 delete($TypeInfo{$LibVersion}{$Tid});
9853 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009854 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009855
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009856 if($Kind eq "Extra")
9857 { # remove duplicates
9858 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9859 {
9860 if($UsedType{$Tid})
9861 { # All & Extended
9862 next;
9863 }
9864
9865 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9866
9867 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9868 delete($TypeInfo{$LibVersion}{$Tid});
9869 }
9870 }
9871 }
9872
9873 foreach my $Tid (keys(%Delete))
9874 {
9875 delete($TypeInfo{$LibVersion}{$Tid});
9876 }
9877}
9878
9879sub check_Completeness($$)
9880{
9881 my ($Info, $LibVersion) = @_;
9882
9883 # data types
9884 if(defined $Info->{"Memb"})
9885 {
9886 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9887 {
9888 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9889 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9890 }
9891 }
9892 }
9893 if(defined $Info->{"Base"})
9894 {
9895 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9896 check_TypeInfo($Bid, $LibVersion);
9897 }
9898 }
9899 if(defined $Info->{"BaseType"}) {
9900 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9901 }
9902 if(defined $Info->{"TParam"})
9903 {
9904 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9905 {
9906 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9907 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9908 next;
9909 }
9910 if($TName eq "_BoolType") {
9911 next;
9912 }
9913 if($TName=~/\Asizeof\(/) {
9914 next;
9915 }
9916 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9917 check_TypeInfo($Tid, $LibVersion);
9918 }
9919 else
9920 {
9921 if(defined $Debug) {
9922 printMsg("WARNING", "missed type $TName");
9923 }
9924 }
9925 }
9926 }
9927
9928 # symbols
9929 if(defined $Info->{"Param"})
9930 {
9931 foreach my $Pos (keys(%{$Info->{"Param"}}))
9932 {
9933 if(defined $Info->{"Param"}{$Pos}{"type"}) {
9934 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
9935 }
9936 }
9937 }
9938 if(defined $Info->{"Return"}) {
9939 check_TypeInfo($Info->{"Return"}, $LibVersion);
9940 }
9941 if(defined $Info->{"Class"}) {
9942 check_TypeInfo($Info->{"Class"}, $LibVersion);
9943 }
9944}
9945
9946sub check_TypeInfo($$)
9947{
9948 my ($Tid, $LibVersion) = @_;
9949
9950 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
9951 return;
9952 }
9953 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
9954
9955 if(defined $TypeInfo{$LibVersion}{$Tid})
9956 {
9957 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
9958 printMsg("ERROR", "missed type name ($Tid)");
9959 }
9960 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
9961 }
9962 else {
9963 printMsg("ERROR", "missed type id $Tid");
9964 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009965}
9966
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009967sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009968{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009969 my ($TypeId, $LibVersion) = @_;
9970 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009971 if($Type{"Type"} eq "Typedef")
9972 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009973 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009974 if($Base{"Type"}=~/Class|Struct/)
9975 {
9976 if($Type{"Name"} eq $Base{"Name"}) {
9977 return 1;
9978 }
9979 elsif($Type{"Name"}=~/::(\w+)\Z/)
9980 {
9981 if($Type{"Name"} eq $Base{"Name"}."::".$1)
9982 { # QPointer<QWidget>::QPointer
9983 return 1;
9984 }
9985 }
9986 }
9987 }
9988 return 0;
9989}
9990
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009991sub addExtension($)
9992{
9993 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009994 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009995 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009996 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009997 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009998 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9999 $TName=~s/\A(struct|union|class|enum) //;
10000 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010001
10002 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10003 "Header" => "extended.h",
10004 "ShortName" => $Symbol,
10005 "MnglName" => $Symbol,
10006 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10007 );
10008
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010009 $ExtendedSymbols{$Symbol} = 1;
10010 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10011 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010012 }
10013 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010014 $ExtendedSymbols{"external_func_0"} = 1;
10015 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10016 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010017}
10018
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010019sub findMethod($$$)
10020{
10021 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010022 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010023 {
10024 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10025 return $VirtMethodInClass;
10026 }
10027 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10028 return $VirtMethodInBaseClasses;
10029 }
10030 }
10031 return "";
10032}
10033
10034sub findMethod_Class($$$)
10035{
10036 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010037 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010038 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10039 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10040 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10041 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10042 { # search for interface with the same parameters suffix (overridden)
10043 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10044 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010045 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10046 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010047 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10048 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010049 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10050 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10051 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10052 return $Candidate;
10053 }
10054 }
10055 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010056 else
10057 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010058 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10059 return $Candidate;
10060 }
10061 }
10062 }
10063 }
10064 return "";
10065}
10066
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010067sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010068{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010069 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010070 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010071 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010072 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10073 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010074 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010075 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010076 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010077 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10078 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010079 { # pure virtual D2-destructors are marked as "virt" in the dump
10080 # virtual D2-destructors are NOT marked as "virt" in the dump
10081 # both destructors are not presented in the v-table
10082 next;
10083 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010084 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010085 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010087 }
10088}
10089
10090sub registerOverriding($)
10091{
10092 my $LibVersion = $_[0];
10093 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010094 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010095 foreach my $ClassName (@Classes)
10096 {
10097 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10098 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010099 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10100 { # pure virtuals
10101 next;
10102 }
10103 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10104 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010105 {
10106 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10107 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10108 { # both overridden virtual methods
10109 # and implemented pure virtual methods
10110 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10111 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10112 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10113 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010114 }
10115 }
10116 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10117 delete($VirtualTable{$LibVersion}{$ClassName});
10118 }
10119 }
10120}
10121
10122sub setVirtFuncPositions($)
10123{
10124 my $LibVersion = $_[0];
10125 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10126 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010127 my ($Num, $Rel) = (1, 0);
10128
10129 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010130 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010131 if($UsedDump{$LibVersion}{"DWARF"}) {
10132 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10133 }
10134 else {
10135 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10136 }
10137 foreach my $VirtFunc (@Funcs)
10138 {
10139 if($UsedDump{$LibVersion}{"DWARF"}) {
10140 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10141 }
10142 else {
10143 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10144 }
10145
10146 # set relative positions
10147 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10148 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10149 { # relative position excluding added and removed virtual functions
10150 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10151 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10152 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010156 }
10157 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010158 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010159 {
10160 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010161 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010162 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010163 }
10164 }
10165}
10166
10167sub get_sub_classes($$$)
10168{
10169 my ($ClassId, $LibVersion, $Recursive) = @_;
10170 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10171 my @Subs = ();
10172 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10173 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010174 if($Recursive)
10175 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010176 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10177 push(@Subs, $SubSubId);
10178 }
10179 }
10180 push(@Subs, $SubId);
10181 }
10182 return @Subs;
10183}
10184
10185sub get_base_classes($$$)
10186{
10187 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010188 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010189 return () if(not defined $ClassType{"Base"});
10190 my @Bases = ();
10191 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10192 keys(%{$ClassType{"Base"}}))
10193 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010194 if($Recursive)
10195 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010196 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10197 push(@Bases, $SubBaseId);
10198 }
10199 }
10200 push(@Bases, $BaseId);
10201 }
10202 return @Bases;
10203}
10204
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010205sub getVTable_Model($$)
10206{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010207 my ($ClassId, $LibVersion) = @_;
10208 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10209 my @Elements = ();
10210 foreach my $BaseId (@Bases, $ClassId)
10211 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010212 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010213 {
10214 if(defined $VirtualTable{$LibVersion}{$BName})
10215 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010216 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10217 if($UsedDump{$LibVersion}{"DWARF"}) {
10218 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10219 }
10220 else {
10221 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10222 }
10223 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010224 push(@Elements, $VFunc);
10225 }
10226 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010227 }
10228 }
10229 return @Elements;
10230}
10231
10232sub getVShift($$)
10233{
10234 my ($ClassId, $LibVersion) = @_;
10235 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10236 my $VShift = 0;
10237 foreach my $BaseId (@Bases)
10238 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010239 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010240 {
10241 if(defined $VirtualTable{$LibVersion}{$BName}) {
10242 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10243 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010244 }
10245 }
10246 return $VShift;
10247}
10248
10249sub getShift($$)
10250{
10251 my ($ClassId, $LibVersion) = @_;
10252 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10253 my $Shift = 0;
10254 foreach my $BaseId (@Bases)
10255 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010256 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010257 {
10258 if($Size!=1)
10259 { # not empty base class
10260 $Shift+=$Size;
10261 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010262 }
10263 }
10264 return $Shift;
10265}
10266
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010267sub getVTable_Size($$)
10268{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010269 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010270 my $Size = 0;
10271 # three approaches
10272 if(not $Size)
10273 { # real size
10274 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10275 $Size = keys(%VTable);
10276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010277 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010278 if(not $Size)
10279 { # shared library symbol size
10280 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10281 $Size /= $WORD_SIZE{$LibVersion};
10282 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010283 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010284 if(not $Size)
10285 { # model size
10286 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10287 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10288 }
10289 }
10290 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010291}
10292
10293sub isCopyingClass($$)
10294{
10295 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010296 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010297}
10298
10299sub isLeafClass($$)
10300{
10301 my ($ClassId, $LibVersion) = @_;
10302 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10303}
10304
10305sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010306{ # check structured type for public fields
10307 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010308}
10309
10310sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010311{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010312 my ($TypePtr, $Skip, $Start, $End) = @_;
10313 return 0 if(not $TypePtr);
10314 if($End==-1) {
10315 $End = keys(%{$TypePtr->{"Memb"}})-1;
10316 }
10317 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10318 {
10319 if($Skip and $Skip->{$MemPos})
10320 { # skip removed/added fields
10321 next;
10322 }
10323 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10324 {
10325 if(isPublic($TypePtr, $MemPos)) {
10326 return ($MemPos+1);
10327 }
10328 }
10329 }
10330 return 0;
10331}
10332
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010333sub isReserved($)
10334{ # reserved fields == private
10335 my $MName = $_[0];
10336 if($MName=~/reserved|padding|f_spare/i) {
10337 return 1;
10338 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010339 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010340 return 1;
10341 }
10342 if($MName=~/(pad\d+)/i) {
10343 return 1;
10344 }
10345 return 0;
10346}
10347
10348sub isPublic($$)
10349{
10350 my ($TypePtr, $FieldPos) = @_;
10351 return 0 if(not $TypePtr);
10352 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10353 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10354 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10355 { # by name in C language
10356 # FIXME: add other methods to detect private members
10357 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10358 if($MName=~/priv|abidata|parent_object/i)
10359 { # C-styled private data
10360 return 0;
10361 }
10362 if(lc($MName) eq "abi")
10363 { # ABI information/reserved field
10364 return 0;
10365 }
10366 if(isReserved($MName))
10367 { # reserved fields
10368 return 0;
10369 }
10370 return 1;
10371 }
10372 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10373 { # by access in C++ language
10374 return 1;
10375 }
10376 return 0;
10377}
10378
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010379sub getVTable_Real($$)
10380{
10381 my ($ClassName, $LibVersion) = @_;
10382 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10383 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010384 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010385 if(defined $Type{"VTable"}) {
10386 return %{$Type{"VTable"}};
10387 }
10388 }
10389 return ();
10390}
10391
10392sub cmpVTables($)
10393{
10394 my $ClassName = $_[0];
10395 my $Res = cmpVTables_Real($ClassName, 1);
10396 if($Res==-1) {
10397 $Res = cmpVTables_Model($ClassName);
10398 }
10399 return $Res;
10400}
10401
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010402sub cmpVTables_Model($)
10403{
10404 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010405 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010406 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010407 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010408 return 1;
10409 }
10410 }
10411 return 0;
10412}
10413
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010414sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010415{
10416 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010417 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10418 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010419 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010420 my %VTable_Old = getVTable_Real($ClassName, 1);
10421 my %VTable_New = getVTable_Real($ClassName, 2);
10422 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010423 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010424 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010425 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010426 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010427 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10428 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010429 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010430 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010431 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010432 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010433 my $Entry1 = $VTable_Old{$Offset};
10434 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010435 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010436 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010437 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010438 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010439
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010440 $Entry1 = simpleVEntry($Entry1);
10441 $Entry2 = simpleVEntry($Entry2);
10442 if($Entry1 ne $Entry2)
10443 { # register as changed
10444 if($Entry1=~/::([^:]+)\Z/)
10445 {
10446 my $M1 = $1;
10447 if($Entry2=~/::([^:]+)\Z/)
10448 {
10449 my $M2 = $1;
10450 if($M1 eq $M2)
10451 { # overridden
10452 next;
10453 }
10454 }
10455 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010456 if(differentDumps("G"))
10457 {
10458 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10459 {
10460 # GCC 4.6.1: -0x00000000000000010
10461 # GCC 4.7.0: -16
10462 next;
10463 }
10464 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010465 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010466 }
10467 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010468 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010469}
10470
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010471sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010472{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010473 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010474 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10475 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010476 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010477 { # already registered
10478 next;
10479 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010480 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010481 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010482 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010483 foreach my $Symbol (@Affected)
10484 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010485 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010486 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010487 "Target"=>$ClassName);
10488 }
10489 }
10490 }
10491}
10492
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010493sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010494{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010495 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010496 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010497 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010498 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010499 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010500 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010501 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010502 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010503 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010504 if($TName_Tid{1}{$ClassName}
10505 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010506 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010507 if(defined $CompleteSignature{1}{$Symbol}
10508 and $CompleteSignature{1}{$Symbol}{"Virt"})
10509 { # override some method in v.1
10510 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010511 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010512 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010513 }
10514 }
10515 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010516 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010517 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010518 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010519 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010520 if($TName_Tid{2}{$ClassName}
10521 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010522 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010523 if(defined $CompleteSignature{2}{$Symbol}
10524 and $CompleteSignature{2}{$Symbol}{"Virt"})
10525 { # override some method in v.2
10526 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010527 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010528 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010529 }
10530 }
10531 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010532 if($Level eq "Binary")
10533 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010534 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010535 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10536 { # check replacements, including pure virtual methods
10537 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10538 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010539 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010540 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10541 if($AddedPos==$RemovedPos)
10542 {
10543 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10544 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10545 last; # other methods will be reported as "added" or "removed"
10546 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010547 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010548 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10549 {
10550 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10551 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010552 next;
10553 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010554 my $ProblemType = "Virtual_Replacement";
10555 my @Affected = ($RemovedVFunc);
10556 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10557 { # pure methods
10558 if(not isUsedClass($ClassId, 1, $Level))
10559 { # not a parameter of some exported method
10560 next;
10561 }
10562 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010563
10564 # affected all methods (both virtual and non-virtual ones)
10565 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10566 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010567 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010568 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010569 foreach my $AffectedInt (@Affected)
10570 {
10571 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10572 { # affected exported methods only
10573 next;
10574 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010575 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10576 next;
10577 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010578 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10579 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010580 "Target"=>get_Signature($AddedVFunc, 2),
10581 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010583 }
10584 }
10585 }
10586 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010587 if(not checkDump(1, "2.0")
10588 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010589 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010590 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010591 return;
10592 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010593 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010594 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010595 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010596 next if(not $ClassId_Old);
10597 if(not isCreatable($ClassId_Old, 1))
10598 { # skip classes without public constructors (including auto-generated)
10599 # example: class has only a private exported or private inline constructor
10600 next;
10601 }
10602 if($ClassName=~/>/)
10603 { # skip affected template instances
10604 next;
10605 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010606 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010607 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010608 if(not $ClassId_New) {
10609 next;
10610 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010611 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010612 if($Class_New{"Type"}!~/Class|Struct/)
10613 { # became typedef
10614 if($Level eq "Binary") {
10615 next;
10616 }
10617 if($Level eq "Source")
10618 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010619 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010620 if($Class_New{"Type"}!~/Class|Struct/) {
10621 next;
10622 }
10623 $ClassId_New = $Class_New{"Tid"};
10624 }
10625 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010626
10627 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10628 { # incomplete info in the ABI dump
10629 next;
10630 }
10631
10632
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010633 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10634 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 +040010635
10636 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10637 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10638
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010639 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010640 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10641 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010642 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10643 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010644 my $Shift_Old = getShift($ClassId_Old, 1);
10645 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010646 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010647 my ($Added, $Removed) = (0, 0);
10648 my @StableBases_Old = ();
10649 foreach my $BaseId (@Bases_Old)
10650 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010651 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010652 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010653 push(@StableBases_Old, $BaseId);
10654 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010655 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010656 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010657 { # removed base
10658 # excluding namespace::SomeClass to SomeClass renaming
10659 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010660 if($Level eq "Binary")
10661 { # Binary-level
10662 if($Shift_Old ne $Shift_New)
10663 { # affected fields
10664 if(havePubFields(\%Class_Old)) {
10665 $ProblemKind .= "_And_Shift";
10666 }
10667 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10668 $ProblemKind .= "_And_Size";
10669 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010670 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010671 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10672 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010673 { # affected v-table
10674 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010675 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010676 }
10677 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010678 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010679 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10680 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010681 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10682 {
10683 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10684 if($ProblemKind=~/VTable/) {
10685 $VTableChanged_M{$SubName}=1;
10686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010687 }
10688 }
10689 foreach my $Interface (@Affected)
10690 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010691 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10692 next;
10693 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010694 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010695 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010696 "Target"=>$BaseName,
10697 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10698 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10699 "Shift"=>abs($Shift_New-$Shift_Old) );
10700 }
10701 $Removed+=1;
10702 }
10703 }
10704 my @StableBases_New = ();
10705 foreach my $BaseId (@Bases_New)
10706 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010707 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010708 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010709 push(@StableBases_New, $BaseId);
10710 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010711 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010712 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010713 { # added base
10714 # excluding namespace::SomeClass to SomeClass renaming
10715 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010716 if($Level eq "Binary")
10717 { # Binary-level
10718 if($Shift_Old ne $Shift_New)
10719 { # affected fields
10720 if(havePubFields(\%Class_Old)) {
10721 $ProblemKind .= "_And_Shift";
10722 }
10723 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10724 $ProblemKind .= "_And_Size";
10725 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010726 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010727 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10728 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010729 { # affected v-table
10730 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010731 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010732 }
10733 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010734 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010735 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10736 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010737 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10738 {
10739 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10740 if($ProblemKind=~/VTable/) {
10741 $VTableChanged_M{$SubName}=1;
10742 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010743 }
10744 }
10745 foreach my $Interface (@Affected)
10746 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010747 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10748 next;
10749 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010750 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010751 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010752 "Target"=>$BaseName,
10753 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10754 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10755 "Shift"=>abs($Shift_New-$Shift_Old) );
10756 }
10757 $Added+=1;
10758 }
10759 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010760 if($Level eq "Binary")
10761 { # Binary-level
10762 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010763 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10764 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010765 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010766 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010767 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010768 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010769 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010770 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10771 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010772 if($NewPos!=$OldPos)
10773 { # changed position of the base class
10774 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010775 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010776 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10777 next;
10778 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010779 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10780 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010781 "Target"=>$BaseName,
10782 "Old_Value"=>$OldPos-1,
10783 "New_Value"=>$NewPos-1 );
10784 }
10785 }
10786 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10787 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10788 { # became non-virtual base
10789 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10790 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010791 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10792 next;
10793 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010794 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10795 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010796 "Target"=>$BaseName );
10797 }
10798 }
10799 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10800 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10801 { # became virtual base
10802 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10803 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010804 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10805 next;
10806 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010807 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10808 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010809 "Target"=>$BaseName );
10810 }
10811 }
10812 }
10813 }
10814 # detect size changes in base classes
10815 if($Shift_Old!=$Shift_New)
10816 { # size of allocable class
10817 foreach my $BaseId (@StableBases_Old)
10818 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010819 my %BaseType = get_Type($BaseId, 1);
10820 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010821 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010822 if($Size_Old ne $Size_New
10823 and $Size_Old and $Size_New)
10824 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010825 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010826 if(isCopyingClass($BaseId, 1)) {
10827 $ProblemType = "Size_Of_Copying_Class";
10828 }
10829 elsif($AllocableClass{1}{$BaseType{"Name"}})
10830 {
10831 if($Size_New>$Size_Old)
10832 { # increased size
10833 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010834 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010835 else
10836 { # decreased size
10837 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10838 if(not havePubFields(\%Class_Old))
10839 { # affected class has no public members
10840 next;
10841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010842 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010843 }
10844 next if(not $ProblemType);
10845 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10846 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010847 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10848 next;
10849 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010850 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10851 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010852 "Target"=>$BaseType{"Name"},
10853 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10854 "New_Size"=>$Size_New*$BYTE_SIZE );
10855 }
10856 }
10857 }
10858 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010859 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010860 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010861 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010862 { # compare virtual tables size in base classes
10863 my $VShift_Old = getVShift($ClassId_Old, 1);
10864 my $VShift_New = getVShift($ClassId_New, 2);
10865 if($VShift_Old ne $VShift_New)
10866 { # changes in the base class or changes in the list of base classes
10867 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10868 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10869 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010870 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010871 foreach my $BaseId (@AllBases_Old)
10872 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010873 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010874 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010875 { # lost base
10876 next;
10877 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010878 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10879 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010880 if($VSize_Old!=$VSize_New)
10881 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010882 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010883 { # TODO: affected non-virtual methods?
10884 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010885 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10886 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010887 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010888 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010889 { # skip interfaces that have not changed the absolute virtual position
10890 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010891 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010892 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10893 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010894 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010895 $VTableChanged_M{$BaseType{"Name"}} = 1;
10896 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010897 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10898 { # the reason of the layout change: added virtual functions
10899 next if($VirtualReplacement{$VirtFunc});
10900 my $ProblemType = "Added_Virtual_Method";
10901 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10902 $ProblemType = "Added_Pure_Virtual_Method";
10903 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010904 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010905 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010906 "Target"=>get_Signature($VirtFunc, 2) );
10907 }
10908 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10909 { # the reason of the layout change: removed virtual functions
10910 next if($VirtualReplacement{$VirtFunc});
10911 my $ProblemType = "Removed_Virtual_Method";
10912 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10913 $ProblemType = "Removed_Pure_Virtual_Method";
10914 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010915 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010916 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010917 "Target"=>get_Signature($VirtFunc, 1) );
10918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010919 }
10920 }
10921 }
10922 }
10923 }
10924 }
10925 }
10926}
10927
10928sub isCreatable($$)
10929{
10930 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010931 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010932 or isCopyingClass($ClassId, $LibVersion)) {
10933 return 1;
10934 }
10935 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10936 { # Fix for incomplete data: if this class has
10937 # a base class then it should also has a constructor
10938 return 1;
10939 }
10940 if($ReturnedClass{$LibVersion}{$ClassId})
10941 { # returned by some method of this class
10942 # or any other class
10943 return 1;
10944 }
10945 return 0;
10946}
10947
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010948sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010949{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010950 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010951 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
10952 { # parameter of some exported method
10953 return 1;
10954 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010955 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
10956 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010957 { # method from target class
10958 return 1;
10959 }
10960 return 0;
10961}
10962
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010963sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010964{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010965 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010966 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010967 # - virtual
10968 # - pure-virtual
10969 # - non-virtual
10970 if($CompleteSignature{1}{$Interface}{"Data"})
10971 { # global data is not affected
10972 return;
10973 }
10974 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010975 if(not $Class_Id) {
10976 return;
10977 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010978 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010979 if(cmpVTables_Real($CName, 1)==0)
10980 { # no changes
10981 return;
10982 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010983 $CheckedTypes{$Level}{$CName} = 1;
10984 if($Level eq "Binary")
10985 { # Binary-level
10986 if($CompleteSignature{1}{$Interface}{"PureVirt"}
10987 and not isUsedClass($Class_Id, 1, $Level))
10988 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010989 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010990 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010991 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010992 }
10993 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
10994 {
10995 if(defined $VirtualTable{2}{$CName}{$Func}
10996 and defined $CompleteSignature{2}{$Func})
10997 {
10998 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
10999 and $CompleteSignature{2}{$Func}{"PureVirt"})
11000 { # became pure virtual
11001 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11002 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011003 "Target"=>get_Signature_M($Func, 1) );
11004 $VTableChanged_M{$CName} = 1;
11005 }
11006 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11007 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11008 { # became non-pure virtual
11009 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11010 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011011 "Target"=>get_Signature_M($Func, 1) );
11012 $VTableChanged_M{$CName} = 1;
11013 }
11014 }
11015 }
11016 if($Level eq "Binary")
11017 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011018 # check virtual table structure
11019 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11020 {
11021 next if($Interface eq $AddedVFunc);
11022 next if($VirtualReplacement{$AddedVFunc});
11023 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11024 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11025 { # pure virtual methods affect all others (virtual and non-virtual)
11026 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011027 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011028 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011029 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011030 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011031 elsif(not defined $VirtualTable{1}{$CName}
11032 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011033 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011034 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011035 { # became polymorphous class, added v-table pointer
11036 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011037 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011038 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011039 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011040 }
11041 else
11042 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011043 my $VSize_Old = getVTable_Size($CName, 1);
11044 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011045 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011046 if(isCopyingClass($Class_Id, 1))
11047 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11048 my $ProblemType = "Added_Virtual_Method";
11049 if(isLeafClass($Class_Id, 1)) {
11050 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11051 }
11052 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11053 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011054 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011055 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011056 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011057 else
11058 {
11059 my $ProblemType = "Added_Virtual_Method";
11060 if(isLeafClass($Class_Id, 1)) {
11061 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11062 }
11063 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11064 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011065 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011066 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011067 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011068 }
11069 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011070 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11071 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011072 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011073 if(defined $VirtualTable{1}{$CName}
11074 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011075 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011076 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11077 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011078
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011079 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011080 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011081 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11082 foreach my $ASymbol (@Affected)
11083 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011084 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11085 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011086 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011087 next;
11088 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011089 }
11090 $CheckedSymbols{$Level}{$ASymbol} = 1;
11091 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11092 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011093 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011094 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011095 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011096 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011097 }
11098 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011099 else {
11100 # safe
11101 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011102 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011103 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11104 {
11105 next if($VirtualReplacement{$RemovedVFunc});
11106 if($RemovedVFunc eq $Interface
11107 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11108 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011109 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011110 next;
11111 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011112 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011113 { # became non-polymorphous class, removed v-table pointer
11114 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11115 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011116 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011117 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011118 }
11119 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11120 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11121 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011122 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011123 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011124 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11125 next;
11126 }
11127 my $VPos_New = -1;
11128 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011129 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011130 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11131 }
11132 else
11133 {
11134 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011135 next;
11136 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011137 }
11138 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11139 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11140 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11141 {
11142 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11143 foreach my $ASymbol (@Affected)
11144 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011145 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11146 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011147 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011148 next;
11149 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011150 }
11151 my $ProblemType = "Removed_Virtual_Method";
11152 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11153 $ProblemType = "Removed_Pure_Virtual_Method";
11154 }
11155 $CheckedSymbols{$Level}{$ASymbol} = 1;
11156 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11157 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011158 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011159 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011160 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011161 }
11162 }
11163 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011164 }
11165 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011166 else
11167 { # Source-level
11168 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011169 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011170 next if($Interface eq $AddedVFunc);
11171 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011172 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011173 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11174 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011175 "Target"=>get_Signature($AddedVFunc, 2) );
11176 }
11177 }
11178 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11179 {
11180 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11181 {
11182 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11183 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011184 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011185 }
11186 }
11187 }
11188}
11189
11190sub find_MemberPair_Pos_byName($$)
11191{
11192 my ($Member_Name, $Pair_Type) = @_;
11193 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11194 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11195 {
11196 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11197 {
11198 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11199 $Name=~s/\A[_]+|[_]+\Z//g;
11200 if($Name eq $Member_Name) {
11201 return $MemberPair_Pos;
11202 }
11203 }
11204 }
11205 return "lost";
11206}
11207
11208sub find_MemberPair_Pos_byVal($$)
11209{
11210 my ($Member_Value, $Pair_Type) = @_;
11211 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11212 {
11213 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11214 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11215 return $MemberPair_Pos;
11216 }
11217 }
11218 return "lost";
11219}
11220
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011221sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011222{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011223 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011224 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011225 if( $_->{"T1"} eq $_[0]
11226 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011227 {
11228 return 1;
11229 }
11230 }
11231 return 0;
11232}
11233
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011234sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011235{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011236 my %IDs = (
11237 "T1" => $_[0],
11238 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011239 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011240 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011241}
11242
11243sub isRenamed($$$$$)
11244{
11245 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11246 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11247 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011248 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011249 if(not defined $Type2->{"Memb"}{$MemPos}) {
11250 return "";
11251 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011252 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011253 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011254
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011255 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11256 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011257 if($MemberPair_Pos_Rev eq "lost")
11258 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011259 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11260 { # base type match
11261 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011262 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011263 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11264 { # exact type match
11265 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011266 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011267 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11268 { # size match
11269 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011270 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011271 if(isReserved($Pair_Name))
11272 { # reserved fields
11273 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011274 }
11275 }
11276 return "";
11277}
11278
11279sub isLastElem($$)
11280{
11281 my ($Pos, $TypeRef) = @_;
11282 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11283 if($Name=~/last|count|max|total/i)
11284 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11285 return 1;
11286 }
11287 elsif($Name=~/END|NLIMITS\Z/)
11288 { # __RLIMIT_NLIMITS
11289 return 1;
11290 }
11291 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11292 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11293 { # NImageFormats, NColorRoles
11294 return 1;
11295 }
11296 return 0;
11297}
11298
11299sub nonComparable($$)
11300{
11301 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011302
11303 my $N1 = $T1->{"Name"};
11304 my $N2 = $T2->{"Name"};
11305
11306 $N1=~s/\A(struct|union|enum) //;
11307 $N2=~s/\A(struct|union|enum) //;
11308
11309 if($N1 ne $N2
11310 and not isAnon($N1)
11311 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011312 { # different names
11313 if($T1->{"Type"} ne "Pointer"
11314 or $T2->{"Type"} ne "Pointer")
11315 { # compare base types
11316 return 1;
11317 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011318 if($N1!~/\Avoid\s*\*/
11319 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011320 {
11321 return 1;
11322 }
11323 }
11324 elsif($T1->{"Type"} ne $T2->{"Type"})
11325 { # different types
11326 if($T1->{"Type"} eq "Class"
11327 and $T2->{"Type"} eq "Struct")
11328 { # "class" to "struct"
11329 return 0;
11330 }
11331 elsif($T2->{"Type"} eq "Class"
11332 and $T1->{"Type"} eq "Struct")
11333 { # "struct" to "class"
11334 return 0;
11335 }
11336 else
11337 { # "class" to "enum"
11338 # "union" to "class"
11339 # ...
11340 return 1;
11341 }
11342 }
11343 return 0;
11344}
11345
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011346sub isOpaque($)
11347{
11348 my $T = $_[0];
11349 if(not defined $T->{"Memb"})
11350 {
11351 return 1;
11352 }
11353 return 0;
11354}
11355
11356sub removeVPtr($)
11357{ # support for old ABI dumps
11358 my $TPtr = $_[0];
11359 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11360 if($#Pos>=1)
11361 {
11362 foreach my $Pos (0 .. $#Pos-1)
11363 {
11364 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11365 }
11366 delete($TPtr->{"Memb"}{$#Pos});
11367 }
11368}
11369
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011370sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011371{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011372 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011373 return {} if(not $Type1_Id or not $Type2_Id);
11374
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011375 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011376 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011377 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011378 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011379
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011380 my %Type1 = get_Type($Type1_Id, 1);
11381 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011382 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011383 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011384 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011385
11386 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011387 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11388 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011389
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011390 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11391
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011392 my %SubProblems = ();
11393
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011394 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11395 {
11396 if($Type1_Pure{"Type"}=~/Struct|Union/
11397 and $Type2_Pure{"Type"}=~/Struct|Union/)
11398 {
11399 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11400 {
11401 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11402 "Target"=>$Type1_Pure{"Name"},
11403 "Type_Name"=>$Type1_Pure{"Name"} );
11404
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011405 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011406 }
11407 }
11408 }
11409
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011410 if(not $Type1_Pure{"Size"}
11411 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011412 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011413 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11414 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11415 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011416 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011417 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011418 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011419 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011420 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011421 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011422 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011423 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11424 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11425 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011426
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011427 if(defined $TargetHeadersPath)
11428 {
11429 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11430 return {};
11431 }
11432 }
11433
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011434 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11435 { # support for old ABI dumps
11436 # _vptr field added in 3.0
11437 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11438 {
11439 if(defined $Type2_Pure{"Memb"}
11440 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11441 {
11442 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11443 delete($Type2_Pure{"Memb"}{0});
11444 }
11445 else {
11446 removeVPtr(\%Type2_Pure);
11447 }
11448 }
11449 }
11450 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11451 {
11452 if(defined $Type1_Pure{"Memb"}
11453 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11454 {
11455 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11456 delete($Type1_Pure{"Memb"}{0});
11457 }
11458 else {
11459 removeVPtr(\%Type1_Pure);
11460 }
11461 }
11462 }
11463 }
11464
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011465 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11466 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011467
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011468 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011469 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11470 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011471 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011472 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11473 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011474 if($Base_1{"Name"} ne $Base_2{"Name"})
11475 {
11476 if(differentDumps("G")
11477 or differentDumps("V"))
11478 { # different GCC versions or different dumps
11479 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11480 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11481 # std::__va_list and __va_list
11482 $Base_1{"Name"}=~s/\A(\w+::)+//;
11483 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011484 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11485 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011486 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011487 }
11488 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11489 and $Base_1{"Name"} ne $Base_2{"Name"})
11490 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011491 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011492 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011493 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011494 {
11495 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11496 "Target"=>$Typedef_1{"Name"},
11497 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011498 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11499 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11500 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011501 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11502 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011503 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011504 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011505 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11506 {
11507 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11508 "Target"=>$Typedef_1{"Name"},
11509 "Type_Name"=>$Typedef_1{"Name"},
11510 "Old_Value"=>$Base_1{"Name"},
11511 "New_Value"=>$Base_2{"Name"} );
11512 }
11513 else
11514 {
11515 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11516 "Target"=>$Typedef_1{"Name"},
11517 "Type_Name"=>$Typedef_1{"Name"},
11518 "Old_Value"=>$Base_1{"Name"},
11519 "New_Value"=>$Base_2{"Name"} );
11520 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011522 }
11523 }
11524 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11525 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011526 my $TT1 = $Type1_Pure{"Type"};
11527 my $TT2 = $Type2_Pure{"Type"};
11528
11529 if($TT1 ne $TT2
11530 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011531 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011532 my $Short1 = $Type1_Pure{"Name"};
11533 my $Short2 = $Type2_Pure{"Name"};
11534
11535 $Short1=~s/\A\Q$TT1\E //ig;
11536 $Short2=~s/\A\Q$TT2\E //ig;
11537
11538 if($Short1 eq $Short2)
11539 {
11540 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11541 "Target"=>$Type1_Pure{"Name"},
11542 "Type_Name"=>$Type1_Pure{"Name"},
11543 "Old_Value"=>lc($Type1_Pure{"Type"}),
11544 "New_Value"=>lc($Type2_Pure{"Type"}) );
11545 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011546 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011547 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011548 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011549 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011550 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11551 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11552 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11553 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011554 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011555 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011556 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011557 {
11558 my $ProblemKind = "DataType_Size";
11559 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011560 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011561 {
11562 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11563 $ProblemKind = "Size_Of_Copying_Class";
11564 }
11565 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11566 {
11567 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11568 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11569 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011570 else
11571 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011572 # descreased size of allocable class
11573 # it has no special effects
11574 }
11575 }
11576 }
11577 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11578 "Target"=>$Type1_Pure{"Name"},
11579 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011580 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011581 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011582 }
11583 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011584 if(defined $Type1_Pure{"BaseType"}
11585 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011586 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011587 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11588 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011589 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011590 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11591 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011592 }
11593 }
11594 }
11595 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11596 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11597 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11598 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11599 { # detect removed and renamed fields
11600 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11601 next if(not $Member_Name);
11602 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);
11603 if($MemberPair_Pos eq "lost")
11604 {
11605 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11606 {
11607 if(isUnnamed($Member_Name))
11608 { # support for old-version dumps
11609 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011610 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011611 next;
11612 }
11613 }
11614 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11615 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011616 $RenamedField{$Member_Pos} = $RenamedTo;
11617 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011618 }
11619 else
11620 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011621 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011622 }
11623 }
11624 elsif($Type1_Pure{"Type"} eq "Enum")
11625 {
11626 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11627 next if($Member_Value1 eq "");
11628 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11629 if($MemberPair_Pos ne "lost")
11630 { # renamed
11631 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11632 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11633 if($MemberPair_Pos_Rev eq "lost")
11634 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011635 $RenamedField{$Member_Pos} = $RenamedTo;
11636 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011637 }
11638 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011639 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011640 }
11641 }
11642 else
11643 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011644 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011645 }
11646 }
11647 }
11648 else
11649 { # related
11650 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11651 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11652 }
11653 }
11654 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11655 { # detect added fields
11656 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11657 next if(not $Member_Name);
11658 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);
11659 if($MemberPair_Pos eq "lost")
11660 {
11661 if(isUnnamed($Member_Name))
11662 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011663 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011664 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011665 next;
11666 }
11667 }
11668 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11669 {
11670 if(not $RenamedField_Rev{$Member_Pos})
11671 { # added
11672 $AddedField{$Member_Pos}=1;
11673 }
11674 }
11675 }
11676 }
11677 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11678 { # detect moved fields
11679 my (%RelPos, %RelPosName, %AbsPos) = ();
11680 my $Pos = 0;
11681 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11682 { # relative positions in 1st version
11683 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11684 next if(not $Member_Name);
11685 if(not $RemovedField{$Member_Pos})
11686 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011687 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011688 $RelPosName{1}{$Pos} = $Member_Name;
11689 $AbsPos{1}{$Pos++} = $Member_Pos;
11690 }
11691 }
11692 $Pos = 0;
11693 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11694 { # relative positions in 2nd version
11695 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11696 next if(not $Member_Name);
11697 if(not $AddedField{$Member_Pos})
11698 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011699 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011700 $RelPosName{2}{$Pos} = $Member_Name;
11701 $AbsPos{2}{$Pos++} = $Member_Pos;
11702 }
11703 }
11704 foreach my $Member_Name (keys(%{$RelPos{1}}))
11705 {
11706 my $RPos1 = $RelPos{1}{$Member_Name};
11707 my $AbsPos1 = $NameToPosA{$Member_Name};
11708 my $Member_Name2 = $Member_Name;
11709 if(my $RenamedTo = $RenamedField{$AbsPos1})
11710 { # renamed
11711 $Member_Name2 = $RenamedTo;
11712 }
11713 my $RPos2 = $RelPos{2}{$Member_Name2};
11714 if($RPos2 ne "" and $RPos1 ne $RPos2)
11715 { # different relative positions
11716 my $AbsPos2 = $NameToPosB{$Member_Name2};
11717 if($AbsPos1 ne $AbsPos2)
11718 { # different absolute positions
11719 my $ProblemType = "Moved_Field";
11720 if(not isPublic(\%Type1_Pure, $AbsPos1))
11721 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011722 if($Level eq "Source") {
11723 next;
11724 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011725 $ProblemType = "Moved_Private_Field";
11726 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011727 if($Level eq "Binary"
11728 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011729 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011730 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011731 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011732 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011733 if($MemSize1 ne $MemSize2) {
11734 $ProblemType .= "_And_Size";
11735 }
11736 }
11737 if($ProblemType eq "Moved_Private_Field") {
11738 next;
11739 }
11740 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11741 "Target"=>$Member_Name,
11742 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011743 "Old_Value"=>$RPos1,
11744 "New_Value"=>$RPos2 );
11745 }
11746 }
11747 }
11748 }
11749 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011750 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011751 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11752 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011753 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011754 if(my $RenamedTo = $RenamedField{$Member_Pos})
11755 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011756 if(defined $Constants{2}{$Member_Name})
11757 {
11758 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11759 { # define OLD NEW
11760 next; # Safe
11761 }
11762 }
11763
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011764 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11765 {
11766 if(isPublic(\%Type1_Pure, $Member_Pos))
11767 {
11768 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11769 "Target"=>$Member_Name,
11770 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011771 "Old_Value"=>$Member_Name,
11772 "New_Value"=>$RenamedTo );
11773 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011774 elsif(isReserved($Member_Name))
11775 {
11776 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11777 "Target"=>$Member_Name,
11778 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011779 "Old_Value"=>$Member_Name,
11780 "New_Value"=>$RenamedTo );
11781 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011782 }
11783 elsif($Type1_Pure{"Type"} eq "Enum")
11784 {
11785 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11786 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11787 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011788 "Old_Value"=>$Member_Name,
11789 "New_Value"=>$RenamedTo );
11790 }
11791 }
11792 elsif($RemovedField{$Member_Pos})
11793 { # removed
11794 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11795 {
11796 my $ProblemType = "Removed_Field";
11797 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011798 or isUnnamed($Member_Name))
11799 {
11800 if($Level eq "Source") {
11801 next;
11802 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011803 $ProblemType = "Removed_Private_Field";
11804 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011805 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011806 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011807 {
11808 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11809 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011810 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 +040011811 { # changed offset
11812 $ProblemType .= "_And_Layout";
11813 }
11814 }
11815 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11816 { # affected size
11817 $ProblemType .= "_And_Size";
11818 }
11819 }
11820 if($ProblemType eq "Removed_Private_Field") {
11821 next;
11822 }
11823 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11824 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011825 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011826 }
11827 elsif($Type2_Pure{"Type"} eq "Union")
11828 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011829 if($Level eq "Binary"
11830 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011831 {
11832 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11833 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011834 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011835 }
11836 else
11837 {
11838 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11839 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011840 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011841 }
11842 }
11843 elsif($Type1_Pure{"Type"} eq "Enum")
11844 {
11845 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11846 "Target"=>$Member_Name,
11847 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011848 "Old_Value"=>$Member_Name );
11849 }
11850 }
11851 else
11852 { # changed
11853 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11854 if($Type1_Pure{"Type"} eq "Enum")
11855 {
11856 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11857 next if($Member_Value1 eq "");
11858 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11859 next if($Member_Value2 eq "");
11860 if($Member_Value1 ne $Member_Value2)
11861 {
11862 my $ProblemType = "Enum_Member_Value";
11863 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11864 $ProblemType = "Enum_Last_Member_Value";
11865 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011866 if($SkipConstants{1}{$Member_Name}) {
11867 $ProblemType = "Enum_Private_Member_Value";
11868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011869 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11870 "Target"=>$Member_Name,
11871 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011872 "Old_Value"=>$Member_Value1,
11873 "New_Value"=>$Member_Value2 );
11874 }
11875 }
11876 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11877 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011878 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11879 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11880
11881 if($Access1 ne "private"
11882 and $Access2 eq "private")
11883 {
11884 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11885 "Target"=>$Member_Name,
11886 "Type_Name"=>$Type1_Pure{"Name"});
11887 }
11888 elsif($Access1 ne "protected"
11889 and $Access1 ne "private"
11890 and $Access2 eq "protected")
11891 {
11892 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11893 "Target"=>$Member_Name,
11894 "Type_Name"=>$Type1_Pure{"Name"});
11895 }
11896
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011897 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11898 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011899 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011900 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
11901 $SizeV1 = $BSize1;
11902 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011903 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011904 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
11905 $SizeV2 = $BSize2;
11906 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011907 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
11908 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011909 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011910 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011911 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011912 {
11913 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
11914 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
11915 { # field size change (including anon-structures and unions)
11916 # - same types
11917 # - unnamed types
11918 # - bitfields
11919 my $ProblemType = "Field_Size";
11920 if(not isPublic(\%Type1_Pure, $Member_Pos)
11921 or isUnnamed($Member_Name))
11922 { # should not be accessed by applications, goes to "Low Severity"
11923 # example: "abidata" members in GStreamer types
11924 $ProblemType = "Private_".$ProblemType;
11925 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011926 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 +040011927 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011928 if($Type2_Pure{"Type"} ne "Union"
11929 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011930 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011931 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 +040011932 { # changed offset
11933 $ProblemType .= "_And_Layout";
11934 }
11935 }
11936 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11937 $ProblemType .= "_And_Type_Size";
11938 }
11939 }
11940 if($ProblemType eq "Private_Field_Size")
11941 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011942 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040011943 if($ProblemType eq "Field_Size")
11944 {
11945 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
11946 { # Low severity
11947 $ProblemType = "Struct_Field_Size_Increased";
11948 }
11949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011950 if($ProblemType)
11951 { # register a problem
11952 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11953 "Target"=>$Member_Name,
11954 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011955 "Old_Size"=>$SizeV1,
11956 "New_Size"=>$SizeV2);
11957 }
11958 }
11959 }
11960 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
11961 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
11962 { # do NOT check bitfield type changes
11963 next;
11964 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011965 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011966 {
11967 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11968 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11969 {
11970 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
11971 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011972 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011973 }
11974 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11975 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11976 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011977 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011978 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011979 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011980 }
11981 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011982 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
11983 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011984 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011985 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
11986 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011987
11988 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011989 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011990 or $ProblemType eq "Field_Type_And_Size"
11991 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011992 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011993 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011994 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011995 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011996 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011997 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011998 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011999 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012000 }
12001 }
12002 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12003 {
12004 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012005 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012006 }
12007 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012008 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012009 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012010 }
12011 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12012 {
12013 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012014 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012015 }
12016 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012017 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012018 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012019 }
12020 }
12021 }
12022
12023 if($Level eq "Source")
12024 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012025 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012026 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012027 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12028 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012029
12030 if($ProblemType eq "Field_Type")
12031 {
12032 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012033 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012034 }
12035 }
12036 }
12037 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012038
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012039 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012040 {
12041 my $ProblemType_Init = $ProblemType;
12042 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012043 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012044 if(not isPublic(\%Type1_Pure, $Member_Pos)
12045 or isUnnamed($Member_Name)) {
12046 $ProblemType = "Private_".$ProblemType;
12047 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012048 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 +040012049 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012050 if($Type2_Pure{"Type"} ne "Union"
12051 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012052 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012053 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 +040012054 { # changed offset
12055 $ProblemType .= "_And_Layout";
12056 }
12057 }
12058 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12059 $ProblemType .= "_And_Type_Size";
12060 }
12061 }
12062 }
12063 else
12064 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012065 # TODO: Private_Field_Type rule?
12066
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012067 if(not isPublic(\%Type1_Pure, $Member_Pos)
12068 or isUnnamed($Member_Name)) {
12069 next;
12070 }
12071 }
12072 if($ProblemType eq "Private_Field_Type_And_Size")
12073 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012074 }
12075 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12076 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012077 "Type_Name"=>$Type1_Pure{"Name"});
12078
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012079 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012080 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012081 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012082 }
12083 }
12084 if(not isPublic(\%Type1_Pure, $Member_Pos))
12085 { # do NOT check internal type changes
12086 next;
12087 }
12088 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012089 { # checking member type changes
12090 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12091
12092 my %DupProblems = ();
12093
12094 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012095 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012096 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012097 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012098 if(not defined $AllAffected)
12099 {
12100 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12101 next;
12102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012103 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012104
12105 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12106 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12107
12108 if(not defined $AllAffected)
12109 {
12110 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012111 }
12112 }
12113 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012114
12115 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012116 }
12117 }
12118 }
12119 }
12120 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12121 { # checking added members, public and private
12122 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12123 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012124 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012125 if($AddedField{$Member_Pos})
12126 { # added
12127 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12128 {
12129 my $ProblemType = "Added_Field";
12130 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012131 or isUnnamed($Member_Name))
12132 {
12133 if($Level eq "Source") {
12134 next;
12135 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012136 $ProblemType = "Added_Private_Field";
12137 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012138 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012139 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012140 {
12141 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12142 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012143 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 +040012144 { # changed offset
12145 $ProblemType .= "_And_Layout";
12146 }
12147 }
12148 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12149 $ProblemType .= "_And_Size";
12150 }
12151 }
12152 if($ProblemType eq "Added_Private_Field")
12153 { # skip added private fields
12154 next;
12155 }
12156 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12157 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012158 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012159 }
12160 elsif($Type2_Pure{"Type"} eq "Union")
12161 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012162 if($Level eq "Binary"
12163 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012164 {
12165 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12166 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012167 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012168 }
12169 else
12170 {
12171 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12172 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012173 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012174 }
12175 }
12176 elsif($Type2_Pure{"Type"} eq "Enum")
12177 {
12178 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12179 next if($Member_Value eq "");
12180 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12181 "Target"=>$Member_Name,
12182 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012183 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012184 }
12185 }
12186 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012187
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012188 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012189 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012190}
12191
12192sub isUnnamed($) {
12193 return $_[0]=~/\Aunnamed\d+\Z/;
12194}
12195
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012196sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012197{
12198 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012199 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12200 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12201 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12202 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012203 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012204 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012205 }
12206 return $TypeName;
12207}
12208
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012209sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012210{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012211 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012212 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012213 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12214 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012215 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012216 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12217 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012218 return () if(not $Type{"Type"});
12219 if($Type{"Type"} ne $Type_Type)
12220 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012221 return () if(not $Type{"BaseType"});
12222 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012223 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012224 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012225 return %Type;
12226}
12227
12228my %TypeSpecAttributes = (
12229 "Const" => 1,
12230 "Volatile" => 1,
12231 "ConstVolatile" => 1,
12232 "Restrict" => 1,
12233 "Typedef" => 1
12234);
12235
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012236sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012237{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012238 my ($TypeId, $Info) = @_;
12239 if(not $TypeId or not $Info
12240 or not $Info->{$TypeId}) {
12241 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012242 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012243 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12244 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12245 }
12246 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012247 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012248 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012249 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012250 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012251 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012252 return %Type;
12253}
12254
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012255sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012256{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012257 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012258 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012259 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12260 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012261 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012262 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12263 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012264 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12265 my $PLevel = 0;
12266 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12267 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012268 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012269 return $PLevel if(not $Type{"BaseType"});
12270 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12271 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12272 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012273}
12274
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012275sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012276{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012277 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012278 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012279 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12280 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012281 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012282 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12283 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012284 return %Type if(not $Type{"BaseType"});
12285 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012286 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012287 return %Type;
12288}
12289
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012290sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012291{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012292 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012293 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012294 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12295 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012296 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012297 my $Qual = "";
12298 if($Type{"Type"} eq "Pointer") {
12299 $Qual .= "*";
12300 }
12301 elsif($Type{"Type"} eq "Ref") {
12302 $Qual .= "&";
12303 }
12304 elsif($Type{"Type"} eq "ConstVolatile") {
12305 $Qual .= "const volatile";
12306 }
12307 elsif($Type{"Type"} eq "Const"
12308 or $Type{"Type"} eq "Volatile"
12309 or $Type{"Type"} eq "Restrict") {
12310 $Qual .= lc($Type{"Type"});
12311 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012312 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012313 return $BQual.$Qual;
12314}
12315
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012316sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012317{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012318 my ($TypeId, $Info) = @_;
12319 if(not $TypeId or not $Info
12320 or not $Info->{$TypeId}) {
12321 return ();
12322 }
12323 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012324 return %Type if(not $Type{"BaseType"});
12325 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012326 {
12327 if($Info->{$BTid}) {
12328 return %{$Info->{$BTid}};
12329 }
12330 else { # something is going wrong
12331 return ();
12332 }
12333 }
12334 else {
12335 return %Type;
12336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012337}
12338
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012339sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012340{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012341 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012342 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012343 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12344 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012345}
12346
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012347sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012348{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012349 my $Symbol = $_[0];
12350 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12351}
12352
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012353sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012354 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12355}
12356
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012357sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012358{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012359 my ($SInfo, $LibVersion) = @_;
12360
12361 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012362 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012363 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012364 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012365 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012366 return 1;
12367 }
12368 }
12369 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012370 if(my $ShortName = $SInfo->{"ShortName"})
12371 {
12372 if(index($ShortName,"<")!=-1
12373 and index($ShortName,">")!=-1) {
12374 return 1;
12375 }
12376 }
12377
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012378 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012379}
12380
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012381sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012382{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012383 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012384 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012385 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012386 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012387 { # class specialization
12388 return 1;
12389 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012390 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012391 { # method specialization
12392 return 1;
12393 }
12394 }
12395 return 0;
12396}
12397
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012398sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012399{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012400 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012401
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012402 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012403 { # non-public global data
12404 return 0;
12405 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012406
12407 if(defined $SkipInternal)
12408 {
12409 return 0 if($Symbol=~/($SkipInternal)/);
12410 }
12411
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012412 if($Symbol=~/\A_Z/)
12413 {
12414 if($Symbol=~/[CD][3-4]E/) {
12415 return 0;
12416 }
12417 }
12418
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012419 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012420 { # support for old ABI dumps in --headers-only mode
12421 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12422 {
12423 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12424 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012425 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012426 if(not $PType or $PType eq "Unknown") {
12427 return 0;
12428 }
12429 }
12430 }
12431 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012432 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012433 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012434 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12435
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012436 if($SkipSymbols{$LibVersion}{$Symbol})
12437 { # user defined symbols to ignore
12438 return 0;
12439 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012440
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012441 if($SymbolsListPath and not $SymbolsList{$Symbol})
12442 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012443 if(not $TargetHeadersPath or not $Header
12444 or not is_target_header($Header, 1))
12445 { # -symbols-list | -headers-list
12446 return 0;
12447 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012448 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012449
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012450 if($AppPath and not $SymbolsList_App{$Symbol})
12451 { # user defined symbols (in application)
12452 return 0;
12453 }
12454
12455 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12456
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012457 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12458 if(not $NameSpace and $ClassId)
12459 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012460 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012461 }
12462 if($NameSpace)
12463 { # user defined namespaces to ignore
12464 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12465 return 0;
12466 }
12467 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12468 { # nested namespaces
12469 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12470 return 0;
12471 }
12472 }
12473 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012474 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012475 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012476 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012477 { # --skip-headers or <skip_headers> (not <skip_including>)
12478 if($Skip==1) {
12479 return 0;
12480 }
12481 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012482 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012483 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012484 { # user defined types
12485 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12486
12487 if(not $TypesList{$CName})
12488 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012489 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12490 {
12491 $CName=~s/\A\Q$NS\E\:\://g;
12492 }
12493
12494 if(not $TypesList{$CName})
12495 {
12496 my $Found = 0;
12497
12498 while($CName=~s/\:\:.+?\Z//)
12499 {
12500 if($TypesList{$CName})
12501 {
12502 $Found = 1;
12503 last;
12504 }
12505 }
12506
12507 if(not $Found) {
12508 return 0;
12509 }
12510 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012511 }
12512 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012513
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012514 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12515 { # non-target symbols
12516 return 0;
12517 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012518 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012519 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012520 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12521 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012522 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012523 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12524 { # inline virtual methods
12525 if($Type=~/InlineVirt/) {
12526 return 1;
12527 }
12528 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12529 if(not $Allocable)
12530 { # check bases
12531 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12532 {
12533 if(not isCopyingClass($DCId, $LibVersion))
12534 { # exists a derived class without default c-tor
12535 $Allocable=1;
12536 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012537 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012538 }
12539 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012540 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012541 return 0;
12542 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012543 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012544 else
12545 { # inline non-virtual methods
12546 return 0;
12547 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012548 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012549 }
12550 }
12551 return 1;
12552}
12553
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012554sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012555{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012556 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012557 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12558 {
12559 if(link_symbol($Symbol, 1, "+Deps"))
12560 { # linker can find a new symbol
12561 # in the old-version library
12562 # So, it's not a new symbol
12563 next;
12564 }
12565 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012566 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012567 next;
12568 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012569 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012570 }
12571}
12572
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012573sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012574{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012575 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012576 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12577 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012578 if(link_symbol($Symbol, 2, "+Deps"))
12579 { # linker can find an old symbol
12580 # in the new-version library
12581 next;
12582 }
12583 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012584 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012585 next;
12586 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012587 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012588 }
12589}
12590
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012591sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012592{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012593 my $Level = $_[0];
12594 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012595 { # checking added symbols
12596 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012597 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012598 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012599 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012600 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012601 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012602 { # checking removed symbols
12603 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012604 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012605 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012606 { # skip v-tables for templates, that should not be imported by applications
12607 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012608 if(my $CName = $VTableClass{$Symbol})
12609 {
12610 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12611 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012612 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012613 next;
12614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012615 }
12616 }
12617 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012618 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012619 }
12620 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12621 { # symbols for pure virtual methods cannot be called by clients
12622 next;
12623 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012624 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012625 }
12626}
12627
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012628sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012629{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012630 my ($LibVersion, $V) = @_;
12631 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12632 return $Cache{"checkDump"}{$LibVersion}{$V};
12633 }
12634 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012635}
12636
12637sub detectAdded_H($)
12638{
12639 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012640 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12641 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012642 if($Level eq "Source")
12643 { # remove symbol version
12644 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12645 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012646
12647 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12648 { # skip artificial constructors
12649 next;
12650 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012651 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012652 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12653 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012654 next;
12655 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012656 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012657 next;
12658 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012659 if(not defined $CompleteSignature{1}{$Symbol}
12660 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12661 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012662 if($UsedDump{2}{"SrcBin"})
12663 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012664 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012665 { # support for old and different (!) ABI dumps
12666 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12667 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012668 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012669 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012670 {
12671 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12672 {
12673 if($Lang eq "C")
12674 { # support for old ABI dumps: missed extern "C" functions
12675 next;
12676 }
12677 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012678 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012679 else
12680 {
12681 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012682 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012683 next;
12684 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012685 }
12686 }
12687 }
12688 }
12689 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012690 }
12691 }
12692}
12693
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012694sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012695{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012696 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012697 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12698 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012699 if($Level eq "Source")
12700 { # remove symbol version
12701 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12702 $Symbol=$SN;
12703 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012704 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12705 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012706 next;
12707 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012708 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012709 next;
12710 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012711 if(not defined $CompleteSignature{2}{$Symbol}
12712 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012713 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012714 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012715 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012716 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012717 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012718 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12719 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012720 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012721 if($CheckHeadersOnly)
12722 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012723 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12724 {
12725 if($Lang eq "C")
12726 { # support for old ABI dumps: missed extern "C" functions
12727 next;
12728 }
12729 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012730 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012731 else
12732 {
12733 if(not link_symbol($Symbol, 1, "-Deps"))
12734 { # skip removed inline symbols
12735 next;
12736 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012737 }
12738 }
12739 }
12740 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012741 if(not checkDump(1, "2.15"))
12742 {
12743 if($Symbol=~/_IT_E\Z/)
12744 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12745 next;
12746 }
12747 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012748 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12749 {
12750 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12751 {
12752 if(defined $Constants{2}{$Short})
12753 {
12754 my $Val = $Constants{2}{$Short}{"Value"};
12755 if(defined $Func_ShortName{2}{$Val})
12756 { # old name defined to new
12757 next;
12758 }
12759 }
12760 }
12761
12762 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012763 $RemovedInt{$Level}{$Symbol} = 1;
12764 if($Level eq "Source")
12765 { # search for a source-compatible equivalent
12766 setAlternative($Symbol, $Level);
12767 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012768 }
12769 }
12770}
12771
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012772sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012773{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012774 my $Level = $_[0];
12775 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012776 { # checking added symbols
12777 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012778 next if($CompleteSignature{2}{$Symbol}{"Private"});
12779 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012780 if($Level eq "Binary")
12781 {
12782 if($CompleteSignature{2}{$Symbol}{"InLine"})
12783 {
12784 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12785 { # skip inline non-virtual functions
12786 next;
12787 }
12788 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012789 }
12790 else
12791 { # Source
12792 if($SourceAlternative_B{$Symbol}) {
12793 next;
12794 }
12795 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012796 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012797 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012798 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012799 { # checking removed symbols
12800 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012801 next if($CompleteSignature{1}{$Symbol}{"Private"});
12802 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012803 if($Level eq "Binary")
12804 {
12805 if($CompleteSignature{1}{$Symbol}{"InLine"})
12806 {
12807 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12808 { # skip inline non-virtual functions
12809 next;
12810 }
12811 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012812 }
12813 else
12814 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012815 if(my $Alt = $SourceAlternative{$Symbol})
12816 {
12817 if(defined $CompleteSignature{1}{$Alt}
12818 and $CompleteSignature{1}{$Symbol}{"Const"})
12819 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012820 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012821 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012822 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012823 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012824 }
12825 else
12826 { # do NOT show removed symbol
12827 next;
12828 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012829 }
12830 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012831 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012832 }
12833}
12834
12835sub addParamNames($)
12836{
12837 my $LibraryVersion = $_[0];
12838 return if(not keys(%AddIntParams));
12839 my $SecondVersion = $LibraryVersion==1?2:1;
12840 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
12841 {
12842 next if(not keys(%{$AddIntParams{$Interface}}));
12843 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012844 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012845 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
12846 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012847 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012848 if(defined $CompleteSignature{$SecondVersion}{$Interface}
12849 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
12850 {
12851 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
12852 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12853 }
12854 }
12855 else {
12856 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12857 }
12858 }
12859 }
12860 }
12861}
12862
12863sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012864{ # detect changed typedefs to show
12865 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012866 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
12867 {
12868 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012869 my $BName1 = $Typedef_BaseName{1}{$Typedef};
12870 if(not $BName1 or isAnon($BName1)) {
12871 next;
12872 }
12873 my $BName2 = $Typedef_BaseName{2}{$Typedef};
12874 if(not $BName2 or isAnon($BName2)) {
12875 next;
12876 }
12877 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012878 $ChangedTypedef{$Typedef} = 1;
12879 }
12880 }
12881}
12882
12883sub get_symbol_suffix($$)
12884{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012885 my ($Symbol, $Full) = @_;
12886 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040012887 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012888 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012889 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012890 if(not $Full) {
12891 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
12892 }
12893 return $Suffix;
12894}
12895
12896sub get_symbol_prefix($$)
12897{
12898 my ($Symbol, $LibVersion) = @_;
12899 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
12900 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12901 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012902 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012903 }
12904 return $ShortName;
12905}
12906
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012907sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012908{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012909 my $Symbol = $_[0];
12910 my $PSymbol = $Symbol;
12911 if(not defined $CompleteSignature{2}{$PSymbol}
12912 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
12913 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
12914 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012915 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012916 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012917 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012918 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012919 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
12920 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012921 {
12922 if(defined $CompleteSignature{2}{$PSymbol}
12923 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12924 {
12925 $SourceAlternative{$Symbol} = $PSymbol;
12926 $SourceAlternative_B{$PSymbol} = $Symbol;
12927 if(not defined $CompleteSignature{1}{$PSymbol}
12928 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12929 $SourceReplacement{$Symbol} = $PSymbol;
12930 }
12931 }
12932 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012933 }
12934 else
12935 {
12936 foreach my $Sp ("KV", "VK", "K", "V")
12937 {
12938 if($PSymbol=~s/\A_ZN$Sp/_ZN/
12939 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
12940 {
12941 if(defined $CompleteSignature{2}{$PSymbol}
12942 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12943 {
12944 $SourceAlternative{$Symbol} = $PSymbol;
12945 $SourceAlternative_B{$PSymbol} = $Symbol;
12946 if(not defined $CompleteSignature{1}{$PSymbol}
12947 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12948 $SourceReplacement{$Symbol} = $PSymbol;
12949 }
12950 }
12951 }
12952 $PSymbol = $Symbol;
12953 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012954 }
12955 }
12956 }
12957 return "";
12958}
12959
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012960sub getSymKind($$)
12961{
12962 my ($Symbol, $LibVersion) = @_;
12963 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
12964 {
12965 return "Global_Data";
12966 }
12967 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12968 {
12969 return "Method";
12970 }
12971 return "Function";
12972}
12973
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040012974sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012975{
12976 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012977 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012978
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012979 mergeBases($Level);
12980
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012981 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012982 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012983 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012984 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012985 next;
12986 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012987 if(defined $CompleteSignature{1}{$Symbol}
12988 and $CompleteSignature{1}{$Symbol}{"Header"})
12989 { # double-check added symbol
12990 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012991 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012992 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012993 next;
12994 }
12995 if($Symbol=~/\A(_Z|\?)/)
12996 { # C++
12997 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
12998 }
12999 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13000 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013001 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13002 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013003 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013004 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013005 {
13006 if($TName_Tid{1}{$AffectedClass_Name})
13007 { # class should exist in previous version
13008 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13009 { # old v-table is NOT copied by old applications
13010 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13011 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013012 "Target"=>get_Signature($Symbol, 2),
13013 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013014 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013015 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013016 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013017 }
13018 }
13019 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013020 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13021 { # check all removed exported symbols
13022 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013023 next;
13024 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013025 if(defined $CompleteSignature{2}{$Symbol}
13026 and $CompleteSignature{2}{$Symbol}{"Header"})
13027 { # double-check removed symbol
13028 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013029 }
13030 if($CompleteSignature{1}{$Symbol}{"Private"})
13031 { # skip private methods
13032 next;
13033 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013034 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013035 next;
13036 }
13037 $CheckedSymbols{$Level}{$Symbol} = 1;
13038 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13039 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013040 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13041 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013042 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013043 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13044 {
13045 if($TName_Tid{2}{$AffectedClass_Name})
13046 { # class should exist in newer version
13047 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13048 { # old v-table is NOT copied by old applications
13049 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13050 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013051 "Target"=>get_Signature($OverriddenMethod, 1),
13052 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013053 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013054 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013055 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013056 }
13057 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013058 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013059 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013060 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013061 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013062 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013063 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013064 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013065 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013066 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013067 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013068 {
13069 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13070 "Target"=>$tr_name{$Symbol},
13071 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013072 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013073 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013074 else
13075 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013076 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013077 "Target"=>$tr_name{$Symbol},
13078 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013079 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013080 }
13081 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013082 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013083 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013084 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013085 {
13086 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13087 "Target"=>$tr_name{$Symbol},
13088 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013089 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013090 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013091 else
13092 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013093 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013094 "Target"=>$tr_name{$Symbol},
13095 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013096 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013097 }
13098 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013099 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13100 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13101 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13102 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13103 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013104 {
13105 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013106 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013107 $ProblemType = "Global_Data_Symbol_Changed_Type";
13108 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013109 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13110 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013111 "Old_Type"=>$RTName1,
13112 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013113 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013114 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013115 }
13116 }
13117 }
13118 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013119 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013120 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013121 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013122 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013123 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013124 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013125 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013126 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13127 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013128 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013129 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013130 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013131 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013132 }
13133 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013134 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13135 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013136 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013137 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013138 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013139 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013140 }
13141 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013142 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013143 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013144 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013145 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013146 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013147 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013148 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013149 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013150 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013151 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013152 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013153 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013154 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013155 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013156 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013157 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013158 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013159 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013160 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013161 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013162 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013163 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013164 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013165 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013166 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013167 { # "volatile" to non-"volatile"
13168
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013169 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013170 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013171 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013172 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013173 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013174 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013175 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013176 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013177 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013178 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013179 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013180 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013181 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013182 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013183 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013184 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013185 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013186 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13187 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013188 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013189 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013190 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013191 }
13192 }
13193 }
13194 }
13195 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013196 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13197 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013198 $CurrentSymbol = $Symbol;
13199
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013200 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13201 if($Level eq "Source")
13202 { # remove symbol version
13203 $Symbol=$SN;
13204 }
13205 else
13206 { # Binary
13207 if(not $SV)
13208 { # symbol without version
13209 if(my $VSym = $SymVer{1}{$Symbol})
13210 { # the symbol is linked with versioned symbol
13211 if($CompleteSignature{2}{$VSym}{"MnglName"})
13212 { # show report for symbol@ver only
13213 next;
13214 }
13215 elsif(not link_symbol($VSym, 2, "-Deps"))
13216 { # changed version: sym@v1 to sym@v2
13217 # do NOT show report for symbol
13218 next;
13219 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013220 }
13221 }
13222 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013223 my $PSymbol = $Symbol;
13224 if($Level eq "Source"
13225 and my $S = $SourceReplacement{$Symbol})
13226 { # take a source-compatible replacement function
13227 $PSymbol = $S;
13228 }
13229 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013230 { # private symbols
13231 next;
13232 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013233 if(not defined $CompleteSignature{1}{$Symbol}
13234 or not defined $CompleteSignature{2}{$PSymbol})
13235 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013236 next;
13237 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013238 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13239 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13240 { # no mangled name
13241 next;
13242 }
13243 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13244 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013245 { # without a header
13246 next;
13247 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013248
13249 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13250 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13251 { # became pure
13252 next;
13253 }
13254 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13255 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13256 { # became non-pure
13257 next;
13258 }
13259
13260 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13261 { # exported, target, inline virtual and pure virtual
13262 next;
13263 }
13264 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13265 { # exported, target, inline virtual and pure virtual
13266 next;
13267 }
13268
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013269 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013270 {
13271 if($CompleteSignature{1}{$Symbol}{"Data"}
13272 and $CompleteSignature{2}{$PSymbol}{"Data"})
13273 {
13274 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13275 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13276 if(defined $Value1)
13277 {
13278 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13279 if(defined $Value2)
13280 {
13281 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13282 if($Value1 ne $Value2)
13283 {
13284 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13285 "Old_Value"=>$Value1,
13286 "New_Value"=>$Value2,
13287 "Target"=>get_Signature($Symbol, 1) );
13288 }
13289 }
13290 }
13291 }
13292 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013293
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013294 if($CompleteSignature{2}{$PSymbol}{"Private"})
13295 {
13296 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13297 "Target"=>get_Signature_M($PSymbol, 2) );
13298 }
13299 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13300 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13301 {
13302 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13303 "Target"=>get_Signature_M($PSymbol, 2) );
13304 }
13305 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13306 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13307 {
13308 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13309 "Target"=>get_Signature_M($PSymbol, 2) );
13310 }
13311
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013312 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013313 mergeVirtualTables($Symbol, $Level);
13314
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013315 if($COMPILE_ERRORS)
13316 { # if some errors occurred at the compiling stage
13317 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013318 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013319 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013320 { # missed information about parameters in newer version
13321 next;
13322 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013323 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013324 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013325 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013326 next;
13327 }
13328 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013329 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013330 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013331 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013332 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13333 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013334 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13335 "Target"=>get_Signature($Symbol, 1)
13336 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013337 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013338 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013339 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13340 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013341 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013342 "Target"=>get_Signature($Symbol, 1)
13343 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013344 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013345 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13346 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013347 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013348 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013349 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013350 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13351 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13352 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013353 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013354 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013355 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13356 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013357 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013358 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013359 my $ProblemType = "Virtual_Method_Position";
13360 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13361 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013362 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013363 if(isUsedClass($Class_Id, 1, $Level))
13364 {
13365 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013366 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013367 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013368 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13369 next;
13370 }
13371 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013372 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013373 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13374 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013375 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013376 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013377 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013378 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013379 }
13380 }
13381 }
13382 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013383 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13384 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013385 { # do NOT check type changes in pure virtuals
13386 next;
13387 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013388 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013389 if($Symbol=~/\A(_Z|\?)/
13390 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013391 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013392 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013393 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013394 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013395 }
13396 }
13397 else
13398 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013399 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013400 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013401 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013402 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13403 last if($PType2_Name eq "...");
13404 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13405 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013406 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013407 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013408 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013409 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13410 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013411 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13412 $ParamPos_Prev = "lost";
13413 }
13414 }
13415 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013416 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013417 }
13418 if($ParamPos_Prev eq "lost")
13419 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013420 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013421 {
13422 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013423 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013424 $ProblemType = "Added_Unnamed_Parameter";
13425 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013426 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013427 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013428 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013429 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013430 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013431 }
13432 else
13433 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013434 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013435 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013436 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013437 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13438 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013439 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013440 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013441 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013442 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013443 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013444 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013445 "Param_Type"=>$PType2_Name,
13446 "Old_Value"=>$PName_Old,
13447 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013448 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013449 }
13450 }
13451 else
13452 {
13453 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013454 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013455 $ProblemType = "Added_Middle_Unnamed_Parameter";
13456 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013457 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013458 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013459 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013460 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013461 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013462 }
13463 }
13464 }
13465 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013466 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013467 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013468 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013469 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013470 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013471 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013472 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013473 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013474 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013475 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13476 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013477 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013478 }
13479 }
13480 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013481 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013482 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013483 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013484 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13485 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013486 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13487 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013488 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013489 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013490 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013491 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13492 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013493 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13494 $ParamPos_New = "lost";
13495 }
13496 }
13497 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013498 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013499 }
13500 if($ParamPos_New eq "lost")
13501 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013502 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013503 {
13504 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013505 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013506 $ProblemType = "Removed_Unnamed_Parameter";
13507 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013508 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013509 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013510 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013511 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013512 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013513 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013514 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013515 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013516 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013517 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013518 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013519 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013520 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013521 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013522 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013523 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013524 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013525 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013526 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013527 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013528 "Old_Value"=>$PName,
13529 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013530 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013531 }
13532 }
13533 else
13534 {
13535 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013536 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013537 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13538 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013539 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013540 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013541 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013542 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013543 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013544 }
13545 }
13546 }
13547 }
13548 }
13549 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013550 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13551 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013552 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013553
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013554 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013555 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013556 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13557 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013558 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013559
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013560 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013561 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013562 if($SubProblemType eq "Return_Type_And_Size") {
13563 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13564 }
13565 elsif($SubProblemType eq "Return_Type_Format") {
13566 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13567 }
13568 else {
13569 $ProblemTypes{"Global_Data_Type"} = 1;
13570 }
13571
13572 # quals
13573 if($SubProblemType eq "Return_Type"
13574 or $SubProblemType eq "Return_Type_And_Size"
13575 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013576 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013577 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13578 { # const to non-const
13579 if($RR==2) {
13580 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13581 }
13582 else {
13583 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13584 }
13585 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013586 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013587 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13588 { # non-const to const
13589 if($RA==2) {
13590 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13591 }
13592 else {
13593 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13594 }
13595 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013596 }
13597 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013598 }
13599 else
13600 {
13601 # quals
13602 if($SubProblemType eq "Return_Type"
13603 or $SubProblemType eq "Return_Type_And_Size"
13604 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013605 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013606 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013607 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013608 if(addedQual($Old_Value, $New_Value, "volatile"))
13609 {
13610 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13611 if($Level ne "Source"
13612 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13613 $ProblemTypes{"Return_Type"} = 1;
13614 }
13615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013616 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013617 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13618 {
13619 if($RA==2) {
13620 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13621 }
13622 else {
13623 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13624 }
13625 if($Level ne "Source"
13626 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13627 $ProblemTypes{"Return_Type"} = 1;
13628 }
13629 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013630 }
13631 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013632 if($Level eq "Binary"
13633 and not $CompleteSignature{1}{$Symbol}{"Data"})
13634 {
13635 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13636 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13637 { # if one of the architectures is unknown
13638 # then set other arhitecture to unknown too
13639 ($Arch1, $Arch2) = ("unknown", "unknown");
13640 }
13641 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013642 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013643 {
13644 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13645 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13646 }
13647 else
13648 {
13649 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13650 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13651 }
13652
13653 if($SubProblemType eq "Return_Type_Became_Void")
13654 {
13655 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13656 { # parameters stack has been affected
13657 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013658 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013659 }
13660 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013661 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013662 }
13663 }
13664 }
13665 elsif($SubProblemType eq "Return_Type_From_Void")
13666 {
13667 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13668 { # parameters stack has been affected
13669 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013670 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013671 }
13672 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013673 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013674 }
13675 }
13676 }
13677 elsif($SubProblemType eq "Return_Type"
13678 or $SubProblemType eq "Return_Type_And_Size"
13679 or $SubProblemType eq "Return_Type_Format")
13680 {
13681 if($Conv1{"Method"} ne $Conv2{"Method"})
13682 {
13683 if($Conv1{"Method"} eq "stack")
13684 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013685 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013686 }
13687 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013688 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013689 }
13690 }
13691 else
13692 {
13693 if($Conv1{"Method"} eq "reg")
13694 {
13695 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13696 {
13697 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013698 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013699 }
13700 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013701 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013702 }
13703 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013704 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013705 }
13706 }
13707 }
13708 }
13709 }
13710 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013711
13712 if(not keys(%ProblemTypes))
13713 { # default
13714 $ProblemTypes{$SubProblemType} = 1;
13715 }
13716
13717 foreach my $ProblemType (keys(%ProblemTypes))
13718 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013719 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013720 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013721 }
13722 if($ReturnType1_Id and $ReturnType2_Id)
13723 {
13724 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013725 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13726
13727 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013728
13729 if($CompleteSignature{1}{$Symbol}{"Data"})
13730 {
13731 if($Level eq "Binary")
13732 {
13733 if(get_PLevel($ReturnType1_Id, 1)==0)
13734 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013735 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013736 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013737
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013738 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13739 {
13740 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013741 {
13742 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13743 {
13744 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13745 last;
13746 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013747 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013748 }
13749 }
13750 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013751 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013752 {
13753 if(defined $GlobalDataObject{1}{$Symbol}
13754 and defined $GlobalDataObject{2}{$Symbol})
13755 {
13756 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13757 my $New_Size = $GlobalDataObject{2}{$Symbol};
13758 if($Old_Size!=$New_Size)
13759 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013760 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013761 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013762 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013763 }
13764 }
13765 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013766 }
13767 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013768
13769 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013770 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013771 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013772 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013773 my $NewLocation = "retval";
13774 if($SubLocation and $SubLocation ne "retval") {
13775 $NewLocation = "retval->".$SubLocation;
13776 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013777 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13778 }
13779 }
13780
13781 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13782 {
13783 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13784 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013785 my $NewLocation = "retval";
13786 if($SubLocation and $SubLocation ne "retval") {
13787 $NewLocation = "retval->".$SubLocation;
13788 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013789 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013790 }
13791 }
13792 }
13793
13794 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013795 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13796 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13797 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013798 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013799 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013800 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13801 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013802 if($ThisPtr1_Id and $ThisPtr2_Id)
13803 {
13804 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013805 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13806 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013807 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013808 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013809 {
13810 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013811 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013812 }
13813 }
13814 }
13815 }
13816 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013817 if($Level eq "Binary") {
13818 mergeVTables($Level);
13819 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013820 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13821 $CheckedSymbols{$Level}{$Symbol} = 1;
13822 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013823}
13824
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013825sub rmQuals($$)
13826{
13827 my ($Value, $Qual) = @_;
13828 if(not $Qual) {
13829 return $Value;
13830 }
13831 if($Qual eq "all")
13832 { # all quals
13833 $Qual = "const|volatile|restrict";
13834 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013835 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013836 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013837 }
13838 return $Value;
13839}
13840
13841sub cmpBTypes($$$$)
13842{
13843 my ($T1, $T2, $V1, $V2) = @_;
13844 $T1 = uncover_typedefs($T1, $V1);
13845 $T2 = uncover_typedefs($T2, $V2);
13846 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
13847}
13848
13849sub addedQual($$$)
13850{
13851 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013852 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013853}
13854
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013855sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013856{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013857 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013858 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013859}
13860
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013861sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013862{
13863 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
13864 $Old_Value = uncover_typedefs($Old_Value, $V1);
13865 $New_Value = uncover_typedefs($New_Value, $V2);
13866 if($Old_Value eq $New_Value)
13867 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013868 return 0;
13869 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013870 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013871 { # without a qual
13872 return 0;
13873 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013874 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013875 { # became non-qual
13876 return 1;
13877 }
13878 else
13879 {
13880 my @BQ1 = getQualModel($Old_Value, $Qual);
13881 my @BQ2 = getQualModel($New_Value, $Qual);
13882 foreach (0 .. $#BQ1)
13883 { # removed qual
13884 if($BQ1[$_]==1
13885 and $BQ2[$_]!=1)
13886 {
13887 return 2;
13888 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013889 }
13890 }
13891 return 0;
13892}
13893
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013894sub getQualModel($$)
13895{
13896 my ($Value, $Qual) = @_;
13897 if(not $Qual) {
13898 return $Value;
13899 }
13900
13901 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013902 while($Value=~/(\w+)/ and $1 ne $Qual) {
13903 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013904 }
13905 $Value=~s/[^\*\&\w]+//g;
13906
13907 # modeling
13908 # int*const*const == 011
13909 # int**const == 001
13910 my @Model = ();
13911 my @Elems = split(/[\*\&]/, $Value);
13912 if(not @Elems) {
13913 return (0);
13914 }
13915 foreach (@Elems)
13916 {
13917 if($_ eq $Qual) {
13918 push(@Model, 1);
13919 }
13920 else {
13921 push(@Model, 0);
13922 }
13923 }
13924
13925 return @Model;
13926}
13927
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013928my %StringTypes = map {$_=>1} (
13929 "char*",
13930 "char const*"
13931);
13932
13933my %CharTypes = map {$_=>1} (
13934 "char",
13935 "char const"
13936);
13937
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013938sub showVal($$$)
13939{
13940 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013941 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040013942 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013943 if(substr($Value, 0, 2) eq "_Z")
13944 {
13945 if(my $Unmangled = $tr_name{$Value}) {
13946 return $Unmangled;
13947 }
13948 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013949 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013950 { # strings
13951 return "\"$Value\"";
13952 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013953 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013954 { # characters
13955 return "\'$Value\'";
13956 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013957 if($Value eq "")
13958 { # other
13959 return "\'\'";
13960 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013961 return $Value;
13962}
13963
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013964sub getRegs($$$)
13965{
13966 my ($LibVersion, $Symbol, $Pos) = @_;
13967
13968 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
13969 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013970 my %Regs = ();
13971 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
13972 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013973 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013974 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
13975 }
13976 }
13977
13978 return join(", ", sort keys(%Regs));
13979 }
13980
13981 return undef;
13982}
13983
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013984sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013985{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013986 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013987 if(not $Symbol) {
13988 return;
13989 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013990 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
13991 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
13992 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
13993 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013994 if(not $PType1_Id
13995 or not $PType2_Id) {
13996 return;
13997 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013998
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013999 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014000 { # do not merge "this"
14001 if($PName1 eq "this" or $PName2 eq "this") {
14002 return;
14003 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014004 }
14005
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014006 my %Type1 = get_Type($PType1_Id, 1);
14007 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014008
14009 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14010
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014011 my %BaseType1 = get_BaseType($PType1_Id, 1);
14012 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014013
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014014 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014015
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014016 if($Level eq "Binary")
14017 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014018 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014019 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14020 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14021 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14022 {
14023 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014024 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014025 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014026 }
14027 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14028 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14029 {
14030 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014031 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014032 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014033 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014034 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014035
14036 if(defined $UsedDump{1}{"DWARF"}
14037 and defined $UsedDump{2}{"DWARF"})
14038 {
14039 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14040 {
14041 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14042 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14043 if($Old_Regs and $New_Regs)
14044 {
14045 if($Old_Regs ne $New_Regs)
14046 {
14047 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14048 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014049 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014050 "Old_Value"=>$Old_Regs,
14051 "New_Value"=>$New_Regs );
14052 }
14053 }
14054 elsif($Old_Regs and not $New_Regs)
14055 {
14056 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14057 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014058 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014059 "Old_Value"=>$Old_Regs );
14060 }
14061 elsif(not $Old_Regs and $New_Regs)
14062 {
14063 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14064 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014065 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014066 "New_Value"=>$New_Regs );
14067 }
14068 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14069 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14070 {
14071 if($Old_Offset ne $New_Offset)
14072 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014073 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14074 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14075
14076 $Old_Offset = $Old_Offset - $Start1;
14077 $New_Offset = $New_Offset - $Start2;
14078
14079 if($Old_Offset ne $New_Offset)
14080 {
14081 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14082 "Target"=>$PName1,
14083 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14084 "Old_Value"=>$Old_Offset,
14085 "New_Value"=>$New_Offset );
14086 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014087 }
14088 }
14089 }
14090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014091 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014092 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14093 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014094 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014095 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014096 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14097 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014098 if(not checkDump(1, "2.13")
14099 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014100 { # support for old ABI dumps
14101 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014102 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014103 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014104 and $Value_Old eq "false" and $Value_New eq "0")
14105 { # int class::method ( bool p = 0 );
14106 # old ABI dumps: "false"
14107 # new ABI dumps: "0"
14108 $Value_Old = "0";
14109 }
14110 }
14111 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014112 if(not checkDump(1, "2.18")
14113 and checkDump(2, "2.18"))
14114 { # support for old ABI dumps
14115 if(not defined $Value_Old
14116 and substr($Value_New, 0, 2) eq "_Z") {
14117 $Value_Old = $Value_New;
14118 }
14119 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014120 if(defined $Value_Old)
14121 {
14122 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14123 if(defined $Value_New)
14124 {
14125 $Value_New = showVal($Value_New, $PType2_Id, 2);
14126 if($Value_Old ne $Value_New)
14127 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014128 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014129 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014130 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014131 "Old_Value"=>$Value_Old,
14132 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014133 }
14134 }
14135 else
14136 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014137 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014138 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014139 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014140 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014141 }
14142 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014143 elsif(defined $Value_New)
14144 {
14145 $Value_New = showVal($Value_New, $PType2_Id, 2);
14146 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14147 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014148 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014149 "New_Value"=>$Value_New );
14150 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014151 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014152
14153 if($ChkRnmd)
14154 {
14155 if($PName1 and $PName2 and $PName1 ne $PName2
14156 and $PType1_Id!=-1 and $PType2_Id!=-1
14157 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14158 { # except unnamed "..." value list (Id=-1)
14159 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14160 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014161 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014162 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14163 "Old_Value"=>$PName1,
14164 "New_Value"=>$PName2,
14165 "New_Signature"=>get_Signature($Symbol, 2) );
14166 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014167 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014168
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014169 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014170 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014171
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014172 foreach my $SubProblemType (keys(%SubProblems))
14173 { # add new problems, remove false alarms
14174 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14175 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014176
14177 # quals
14178 if($SubProblemType eq "Parameter_Type"
14179 or $SubProblemType eq "Parameter_Type_And_Size"
14180 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014181 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014182 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014183 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014184 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014185 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014186 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014187 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14188 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14189 }
14190 }
14191 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14192 {
14193 if(removedQual($Old_Value, $New_Value, "volatile")) {
14194 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014195 }
14196 }
14197 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14198 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14199 { # int to "int const"
14200 delete($SubProblems{$SubProblemType});
14201 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014202 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014203 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14204 { # "int const" to int
14205 delete($SubProblems{$SubProblemType});
14206 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014207 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14208 { # "const" to non-"const"
14209 if($RR==2) {
14210 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14211 }
14212 else {
14213 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14214 }
14215 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014216 }
14217 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014218
14219 if($Level eq "Source")
14220 {
14221 foreach my $SubProblemType (keys(%SubProblems))
14222 {
14223 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14224 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14225
14226 if($SubProblemType eq "Parameter_Type")
14227 {
14228 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14229 delete($SubProblems{$SubProblemType});
14230 }
14231 }
14232 }
14233 }
14234
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014235 foreach my $SubProblemType (keys(%SubProblems))
14236 { # modify/register problems
14237 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14238 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014239 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14240 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014241
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014242 my $NewProblemType = $SubProblemType;
14243 if($Old_Value eq "..." and $New_Value ne "...")
14244 { # change from "..." to "int"
14245 if($ParamPos1==0)
14246 { # ISO C requires a named argument before "..."
14247 next;
14248 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014249 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014250 }
14251 elsif($New_Value eq "..." and $Old_Value ne "...")
14252 { # change from "int" to "..."
14253 if($ParamPos2==0)
14254 { # ISO C requires a named argument before "..."
14255 next;
14256 }
14257 $NewProblemType = "Parameter_Became_VaList";
14258 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014259 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014260 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014261 {
14262 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014263 if($Arch1 eq "unknown"
14264 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014265 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014266 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014267 ($Arch1, $Arch2) = ("unknown", "unknown");
14268 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014269 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014270 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014271 { # real
14272 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14273 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14274 }
14275 else
14276 { # model
14277 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14278 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14279 }
14280 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014281 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014282 if($Conv1{"Method"} eq "stack")
14283 {
14284 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14285 $NewProblemType = "Parameter_Type_And_Stack";
14286 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014287 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014288 elsif($Conv1{"Method"} eq "reg")
14289 {
14290 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14291 $NewProblemType = "Parameter_Type_And_Register";
14292 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014293 }
14294 }
14295 else
14296 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014297 if($Conv1{"Method"} eq "stack") {
14298 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014299 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014300 elsif($Conv1{"Method"} eq "register") {
14301 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014302 }
14303 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014304 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14305 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014306 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014307 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014308 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014309 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014310 "New_Signature"=>get_Signature($Symbol, 2) );
14311 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014312 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014313
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014314 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014315
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014316 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014317 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14318 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014319 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014320 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014321 {
14322 my $NewProblemType = $SubProblemType;
14323 if($SubProblemType eq "DataType_Size")
14324 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014325 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014326 { # stack has been affected
14327 $NewProblemType = "DataType_Size_And_Stack";
14328 }
14329 }
14330 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014331 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014332 }
14333 }
14334}
14335
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014336sub find_ParamPair_Pos_byName($$$)
14337{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014338 my ($Name, $Symbol, $LibVersion) = @_;
14339 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014340 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014341 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14342 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014343 {
14344 return $ParamPos;
14345 }
14346 }
14347 return "lost";
14348}
14349
14350sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14351{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014352 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014353 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014354 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014355 {
14356 next if($Order eq "backward" and $ParamPos>$MediumPos);
14357 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014358 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14359 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014360 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014361 push(@Positions, $ParamPos);
14362 }
14363 }
14364 return @Positions;
14365}
14366
14367sub getTypeIdByName($$)
14368{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014369 my ($TypeName, $LibVersion) = @_;
14370 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014371}
14372
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014373sub diffTypes($$$)
14374{
14375 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14376 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14377 }
14378 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14379 { # skip recursive declarations
14380 return 0;
14381 }
14382
14383 pushType($_[0], $_[1], \@RecurTypes_Diff);
14384 my $Diff = diffTypes_I(@_);
14385 pop(@RecurTypes_Diff);
14386
14387 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14388}
14389
14390sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014391{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014392 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014393
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014394 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14395 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014396
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014397 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14398 { # equal types
14399 return 0;
14400 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014401 if($Type1_Pure{"Name"} eq "void")
14402 { # from void* to something
14403 return 0;
14404 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014405 if($Type1_Pure{"Name"}=~/\*/
14406 or $Type2_Pure{"Name"}=~/\*/)
14407 { # compared in detectTypeChange()
14408 return 0;
14409 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014410
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014411 my %FloatType = map {$_=>1} (
14412 "float",
14413 "double",
14414 "long double"
14415 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014416
14417 my $T1 = $Type1_Pure{"Type"};
14418 my $T2 = $Type2_Pure{"Type"};
14419
14420 if($T1 eq "Struct"
14421 and $T2 eq "Class")
14422 { # compare as data structures
14423 $T2 = "Struct";
14424 }
14425
14426 if($T1 eq "Class"
14427 and $T2 eq "Struct")
14428 { # compare as data structures
14429 $T1 = "Struct";
14430 }
14431
14432 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014433 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014434 if($T1 eq "Intrinsic"
14435 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014436 { # "int" to "enum"
14437 return 0;
14438 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014439 elsif($T2 eq "Intrinsic"
14440 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014441 { # "enum" to "int"
14442 return 0;
14443 }
14444 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014445 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014446 # ...
14447 return 1;
14448 }
14449 }
14450 else
14451 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014452 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014453 {
14454 if($FloatType{$Type1_Pure{"Name"}}
14455 or $FloatType{$Type2_Pure{"Name"}})
14456 { # "float" to "double"
14457 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014458 if($Level eq "Source")
14459 { # Safe
14460 return 0;
14461 }
14462 else {
14463 return 1;
14464 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014465 }
14466 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014467 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014468 {
14469 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14470 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014471 if(not @Membs1
14472 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014473 { # private
14474 return 0;
14475 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014476 if($#Membs1!=$#Membs2)
14477 { # different number of elements
14478 return 1;
14479 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014480 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014481 {
14482 foreach my $Pos (@Membs1)
14483 { # compare elements by name and value
14484 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14485 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14486 { # different names
14487 return 1;
14488 }
14489 }
14490 }
14491 else
14492 {
14493 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014494 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014495 if($Level eq "Source")
14496 {
14497 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14498 { # different names
14499 return 1;
14500 }
14501 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014502
14503 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14504 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14505
14506 if($MT1{"Name"} ne $MT2{"Name"}
14507 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14508 {
14509 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14510 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14511
14512 if($PL1 ne $PL2)
14513 { # different pointer level
14514 return 1;
14515 }
14516
14517 # compare base types
14518 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14519 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14520
14521 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14522 { # different types
14523 return 1;
14524 }
14525 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014526 }
14527 }
14528 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014529 else
14530 {
14531 # TODO: arrays, etc.
14532 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014533 }
14534 return 0;
14535}
14536
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014537sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014538{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014539 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014540 if(not $Type1_Id or not $Type2_Id) {
14541 return ();
14542 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014543 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014544 my %Type1 = get_Type($Type1_Id, 1);
14545 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014546 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14547 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14548 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14549 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 +040014550
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014551 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14552 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014553 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14554 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14555 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14556 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14557 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14558 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14559 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014560 if($Type1{"Name"} eq $Type2{"Name"})
14561 {
14562 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14563 { # will be reported in mergeTypes() as typedef problem
14564 return ();
14565 }
14566 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14567 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14568 if(%Typedef_1 and %Typedef_2)
14569 {
14570 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14571 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14572 { # const Typedef
14573 return ();
14574 }
14575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014576 }
14577 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14578 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014579 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014580 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14581 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014582 {
14583 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14584 "Old_Value"=>$Type1_Base{"Name"},
14585 "New_Value"=>$Type2_Base{"Name"},
14586 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014587 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014588 }
14589 else
14590 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014591 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014592 { # format change
14593 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14594 "Old_Value"=>$Type1_Base{"Name"},
14595 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014596 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014597 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014598 }
14599 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14600 {
14601 %{$LocalProblems{$Prefix."_BaseType"}}=(
14602 "Old_Value"=>$Type1_Base{"Name"},
14603 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014604 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014605 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014606 }
14607 }
14608 }
14609 }
14610 elsif($Type1{"Name"} ne $Type2{"Name"})
14611 { # type change
14612 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14613 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014614 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014615 and $Type1_Pure{"Name"} eq "void")
14616 {
14617 %{$LocalProblems{"Return_Type_From_Void"}}=(
14618 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014619 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014621 elsif($Prefix eq "Return"
14622 and $Type2_Pure{"Name"} eq "void")
14623 {
14624 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14625 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014626 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014627 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014628 else
14629 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014630 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014631 and $Type1{"Size"} and $Type2{"Size"}
14632 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014633 {
14634 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14635 "Old_Value"=>$Type1{"Name"},
14636 "New_Value"=>$Type2{"Name"},
14637 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014638 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014639 }
14640 else
14641 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014642 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014643 { # format change
14644 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14645 "Old_Value"=>$Type1{"Name"},
14646 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014647 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014648 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014649 }
14650 elsif(tNameLock($Type1_Id, $Type2_Id))
14651 { # FIXME: correct this condition
14652 %{$LocalProblems{$Prefix."_Type"}}=(
14653 "Old_Value"=>$Type1{"Name"},
14654 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014655 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014656 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014657 }
14658 }
14659 }
14660 }
14661 }
14662 if($Type1_PLevel!=$Type2_PLevel)
14663 {
14664 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14665 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14666 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014667 if($Level eq "Source")
14668 {
14669 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014670 "Old_Value"=>$Type1_PLevel,
14671 "New_Value"=>$Type2_PLevel);
14672 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014673 else
14674 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014675 if($Type2_PLevel>$Type1_PLevel)
14676 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014677 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14678 "Old_Value"=>$Type1_PLevel,
14679 "New_Value"=>$Type2_PLevel);
14680 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014681 else
14682 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014683 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14684 "Old_Value"=>$Type1_PLevel,
14685 "New_Value"=>$Type2_PLevel);
14686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014687 }
14688 }
14689 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014690 if($Type1_Pure{"Type"} eq "Array"
14691 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014692 { # base_type[N] -> base_type[N]
14693 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014694 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014695 foreach my $SubProblemType (keys(%SubProblems))
14696 {
14697 $SubProblemType=~s/_Type/_BaseType/g;
14698 next if(defined $LocalProblems{$SubProblemType});
14699 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14700 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14701 }
14702 }
14703 }
14704 return %LocalProblems;
14705}
14706
14707sub tNameLock($$)
14708{
14709 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014710 my $Changed = 0;
14711 if(differentDumps("G"))
14712 { # different GCC versions
14713 $Changed = 1;
14714 }
14715 elsif(differentDumps("V"))
14716 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014717 if(not checkDump(1, "2.20")
14718 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014719 { # latest names update
14720 # 2.6: added restrict qualifier
14721 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014722 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014723 $Changed = 1;
14724 }
14725 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014726
14727 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14728 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14729
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014730 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14731 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14732
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014733 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014734 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014735 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014736 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014737 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014738 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014739 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014740 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014741 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014742 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014743 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14744 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14745 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014746 { # equal base types
14747 return 0;
14748 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014749
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014750 if(not checkDump(1, "2.13")
14751 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014752 { # broken array names in ABI dumps < 2.13
14753 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014754 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014755 return 0;
14756 }
14757 }
14758
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014759 if(not checkDump(1, "2.6")
14760 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014761 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014762 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014763 and $TN2=~/\brestrict\b/) {
14764 return 0;
14765 }
14766 }
14767
14768 if(not checkDump(1, "2.20")
14769 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014770 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014771 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14772 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014773 return 0;
14774 }
14775 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014776 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014777 else
14778 {
14779 # typedef struct {...} type_t
14780 # typedef struct type_t {...} type_t
14781 if(index($TN1, " ".$TN2)!=-1)
14782 {
14783 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14784 return 0;
14785 }
14786 }
14787 if(index($TN2, " ".$TN1)!=-1)
14788 {
14789 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14790 return 0;
14791 }
14792 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014793
14794 if($TT1 eq "FuncPtr"
14795 and $TT2 eq "FuncPtr")
14796 {
14797 my $TN1_C = $TN1;
14798 my $TN2_C = $TN2;
14799
14800 $TN1_C=~s/\b(struct|union) //g;
14801 $TN2_C=~s/\b(struct|union) //g;
14802
14803 if($TN1_C eq $TN2_C) {
14804 return 0;
14805 }
14806 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014807 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014808
14809 my ($N1, $N2) = ($TN1, $TN2);
14810 $N1=~s/\b(struct|union) //g;
14811 $N2=~s/\b(struct|union) //g;
14812
14813 if($N1 eq $N2)
14814 { # QList<struct QUrl> and QList<QUrl>
14815 return 0;
14816 }
14817
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014818 return 1;
14819}
14820
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014821sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014822{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014823 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014824 if(defined $Cache{"differentDumps"}{$Check}) {
14825 return $Cache{"differentDumps"}{$Check};
14826 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014827 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014828 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014829 if($Check eq "G")
14830 {
14831 if(getGccVersion(1) ne getGccVersion(2))
14832 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014833 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014834 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014835 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014836 if($Check eq "V")
14837 {
14838 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14839 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14840 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014841 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014842 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014843 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014844 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014845 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014846}
14847
14848sub formatVersion($$)
14849{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014850 my ($V, $Digits) = @_;
14851 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014852 return join(".", splice(@Elems, 0, $Digits));
14853}
14854
14855sub htmlSpecChars($)
14856{
14857 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014858 if(not $Str) {
14859 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014861 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14862 $Str=~s/</&lt;/g;
14863 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
14864 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014865 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
14866 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014867 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014868 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014869 $Str=~s/\n/<br\/>/g;
14870 $Str=~s/\"/&quot;/g;
14871 $Str=~s/\'/&#39;/g;
14872 return $Str;
14873}
14874
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014875sub xmlSpecChars($)
14876{
14877 my $Str = $_[0];
14878 if(not $Str) {
14879 return $Str;
14880 }
14881
14882 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14883 $Str=~s/</&lt;/g;
14884 $Str=~s/>/&gt;/g;
14885
14886 $Str=~s/\"/&quot;/g;
14887 $Str=~s/\'/&#39;/g;
14888
14889 return $Str;
14890}
14891
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014892sub xmlSpecChars_R($)
14893{
14894 my $Str = $_[0];
14895 if(not $Str) {
14896 return $Str;
14897 }
14898
14899 $Str=~s/&amp;/&/g;
14900 $Str=~s/&lt;/</g;
14901 $Str=~s/&gt;/>/g;
14902
14903 $Str=~s/&quot;/"/g;
14904 $Str=~s/&#39;/'/g;
14905
14906 return $Str;
14907}
14908
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014909sub black_name($)
14910{
14911 my $Name = $_[0];
14912 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
14913}
14914
14915sub highLight_Signature($)
14916{
14917 my $Signature = $_[0];
14918 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
14919}
14920
14921sub highLight_Signature_Italic_Color($)
14922{
14923 my $Signature = $_[0];
14924 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
14925}
14926
14927sub separate_symbol($)
14928{
14929 my $Symbol = $_[0];
14930 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
14931 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
14932 ($Name, $Spec, $Ver) = ($1, $2, $3);
14933 }
14934 return ($Name, $Spec, $Ver);
14935}
14936
14937sub cut_f_attrs($)
14938{
14939 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
14940 return $2;
14941 }
14942 return "";
14943}
14944
14945sub highLight_Signature_PPos_Italic($$$$$)
14946{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014947 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
14948 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014949 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
14950 my $Return = "";
14951 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
14952 $Return = $2;
14953 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014954 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014955 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014956 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014957 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014958 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014959 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014960 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014961 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014962 }
14963 return $Signature;
14964 }
14965 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
14966 $Begin.=" " if($Begin!~/ \Z/);
14967 $End = cut_f_attrs($Signature);
14968 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014969 my ($Short, $Params) = split_Signature($Signature);
14970 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014971 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014972 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014973 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014974 $Part=~s/\A\s+|\s+\Z//g;
14975 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
14976 if($Part=~/\([\*]+(\w+)\)/i) {
14977 $ParamName = $1;#func-ptr
14978 }
14979 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
14980 $ParamName = $1;
14981 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014982 if(not $ParamName)
14983 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014984 push(@Parts, $Part_Styled);
14985 next;
14986 }
14987 if($ItalicParams and not $TName_Tid{1}{$Part}
14988 and not $TName_Tid{2}{$Part})
14989 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014990 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014991 if($Param_Pos ne ""
14992 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014993 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014994 }
14995 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014996 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014997 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014998 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014999 }
15000 $Part_Styled=~s/,(\w)/, $1/g;
15001 push(@Parts, $Part_Styled);
15002 }
15003 if(@Parts)
15004 {
15005 foreach my $Num (0 .. $#Parts)
15006 {
15007 if($Num==$#Parts)
15008 { # add ")" to the last parameter
15009 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15010 }
15011 elsif(length($Parts[$Num])<=45) {
15012 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15013 }
15014 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015015 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015016 }
15017 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015018 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015019 }
15020 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015021 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015022 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015023 $Signature=~s!\[\]![&#160;]!g;
15024 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015025 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15026 if($SymbolVersion) {
15027 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15028 }
15029 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015030}
15031
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015032sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015033{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015034 my $Signature = $_[0];
15035 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15036 {
15037 $Signature=~s/\A\Q$ShortName\E\(//g;
15038 cut_f_attrs($Signature);
15039 $Signature=~s/\)\Z//;
15040 return ($ShortName, $Signature);
15041 }
15042
15043 # error
15044 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015045}
15046
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015047sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015048{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015049 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015050 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015051 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15052 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015053 foreach my $Pos (0 .. length($Params) - 1)
15054 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015055 my $S = substr($Params, $Pos, 1);
15056 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015057 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015058 }
15059 if($S eq "," and
15060 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015061 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015062 if($Comma)
15063 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015064 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015065 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015066 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015067 }
15068 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015069 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015070 }
15071 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015072 if(not $Sp)
15073 { # remove spaces
15074 foreach (@Parts)
15075 {
15076 s/\A //g;
15077 s/ \Z//g;
15078 }
15079 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015080 return @Parts;
15081}
15082
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015083sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015084{
15085 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015086 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015087 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015088 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15089 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015090 $Center+=length($1);
15091 }
15092 foreach my $Pos (0 .. length($Sign)-1)
15093 {
15094 my $S = substr($Sign, $Pos, 1);
15095 if($S eq $Target)
15096 {
15097 if($B{"("}==$B{")"}
15098 and $B{"<"}==$B{">"}) {
15099 return $Center;
15100 }
15101 }
15102 if(defined $B{$S}) {
15103 $B{$S}+=1;
15104 }
15105 $Center+=1;
15106 }
15107 return 0;
15108}
15109
15110sub appendFile($$)
15111{
15112 my ($Path, $Content) = @_;
15113 return if(not $Path);
15114 if(my $Dir = get_dirname($Path)) {
15115 mkpath($Dir);
15116 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015117 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015118 print FILE $Content;
15119 close(FILE);
15120}
15121
15122sub writeFile($$)
15123{
15124 my ($Path, $Content) = @_;
15125 return if(not $Path);
15126 if(my $Dir = get_dirname($Path)) {
15127 mkpath($Dir);
15128 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015129 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015130 print FILE $Content;
15131 close(FILE);
15132}
15133
15134sub readFile($)
15135{
15136 my $Path = $_[0];
15137 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015138 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015139 local $/ = undef;
15140 my $Content = <FILE>;
15141 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015142 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015143 $Content=~s/\r/\n/g;
15144 }
15145 return $Content;
15146}
15147
15148sub get_filename($)
15149{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015150 if(defined $Cache{"get_filename"}{$_[0]}) {
15151 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015152 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015153 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15154 return ($Cache{"get_filename"}{$_[0]}=$1);
15155 }
15156 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015157}
15158
15159sub get_dirname($)
15160{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015161 if(defined $Cache{"get_dirname"}{$_[0]}) {
15162 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015163 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015164 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15165 return ($Cache{"get_dirname"}{$_[0]}=$1);
15166 }
15167 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015168}
15169
15170sub separate_path($) {
15171 return (get_dirname($_[0]), get_filename($_[0]));
15172}
15173
15174sub esc($)
15175{
15176 my $Str = $_[0];
15177 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15178 return $Str;
15179}
15180
15181sub readLineNum($$)
15182{
15183 my ($Path, $Num) = @_;
15184 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015185 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015186 foreach (1 ... $Num) {
15187 <FILE>;
15188 }
15189 my $Line = <FILE>;
15190 close(FILE);
15191 return $Line;
15192}
15193
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015194sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015195{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015196 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015197 return () if(not $Path or not -f $Path);
15198 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015199 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15200 {
15201 foreach my $AttrVal (split(/;/, $1))
15202 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015203 if($AttrVal=~/(.+):(.+)/)
15204 {
15205 my ($Name, $Value) = ($1, $2);
15206 $Attributes{$Name} = $Value;
15207 }
15208 }
15209 }
15210 return \%Attributes;
15211}
15212
15213sub is_abs($) {
15214 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15215}
15216
15217sub get_abs_path($)
15218{ # abs_path() should NOT be called for absolute inputs
15219 # because it can change them
15220 my $Path = $_[0];
15221 if(not is_abs($Path)) {
15222 $Path = abs_path($Path);
15223 }
15224 return $Path;
15225}
15226
15227sub get_OSgroup()
15228{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015229 my $N = $Config{"osname"};
15230 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015231 return "macos";
15232 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015233 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015234 return "bsd";
15235 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015236 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015237 return "beos";
15238 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015239 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015240 return "symbian";
15241 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015242 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015243 return "windows";
15244 }
15245 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015246 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015247 }
15248}
15249
15250sub getGccVersion($)
15251{
15252 my $LibVersion = $_[0];
15253 if($GCC_VERSION{$LibVersion})
15254 { # dump version
15255 return $GCC_VERSION{$LibVersion};
15256 }
15257 elsif($UsedDump{$LibVersion}{"V"})
15258 { # old-version dumps
15259 return "unknown";
15260 }
15261 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15262 if(not $GccVersion) {
15263 return "unknown";
15264 }
15265 return $GccVersion;
15266}
15267
15268sub showArch($)
15269{
15270 my $Arch = $_[0];
15271 if($Arch eq "arm"
15272 or $Arch eq "mips") {
15273 return uc($Arch);
15274 }
15275 return $Arch;
15276}
15277
15278sub getArch($)
15279{
15280 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015281
15282 if($TargetArch) {
15283 return $TargetArch;
15284 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015285 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015286 { # dump version
15287 return $CPU_ARCH{$LibVersion};
15288 }
15289 elsif($UsedDump{$LibVersion}{"V"})
15290 { # old-version dumps
15291 return "unknown";
15292 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015293
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015294 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015295}
15296
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015297sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015298{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015299 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015300
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015301 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015302 if(getArch(1) ne getArch(2)
15303 or getArch(1) eq "unknown"
15304 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015305 { # don't show architecture in the header
15306 $ArchInfo="";
15307 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015308 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015309 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015310 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015311 }
15312 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015313 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015314 }
15315 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015316 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015317 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015318
15319 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15320 {
15321 my $M1 = $UsedDump{1}{"M"};
15322 my $M2 = $UsedDump{2}{"M"};
15323
15324 if($M1 eq $M2)
15325 {
15326 $Title .= " report for the <span style='color:Blue;'>$M1</span> object";
15327 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15328 }
15329 else
15330 {
15331 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$Descriptor{1}{"Version"}."</span>)";
15332 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$Descriptor{2}{"Version"}."</span>) objects";
15333 }
15334 }
15335 else
15336 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015337 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015338 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15339 }
15340
15341 $Title .= $ArchInfo;
15342
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015343 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015344 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015345 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015346 $Title = "<h1>".$Title."</h1>\n";
15347 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015348}
15349
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015350sub get_CheckedHeaders($)
15351{
15352 my $LibVersion = $_[0];
15353
15354 my @Headers = ();
15355
15356 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15357 {
15358 my $File = get_filename($Path);
15359 if(not is_target_header($File, $LibVersion)) {
15360 next;
15361 }
15362
15363 if(skipHeader($File, $LibVersion)) {
15364 next;
15365 }
15366
15367 push(@Headers, $Path);
15368 }
15369
15370 return @Headers;
15371}
15372
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015373sub get_SourceInfo()
15374{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015375 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015376
15377 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015378 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015379 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15380 $CheckedHeaders .= "<div class='h_list'>\n";
15381 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015382 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015383 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15384 my $Name = get_filename($Identity);
15385 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15386 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015387 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015388 $CheckedHeaders .= "</div>\n";
15389 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015390 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015391
15392 if(my @Sources = keys(%{$Registered_Sources{1}}))
15393 {
15394 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15395 $CheckedSources .= "<div class='h_list'>\n";
15396 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15397 {
15398 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15399 my $Name = get_filename($Identity);
15400 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15401 $CheckedSources .= $Name.$Comment."<br/>\n";
15402 }
15403 $CheckedSources .= "</div>\n";
15404 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15405 }
15406
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015407 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015408 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015409 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015410 $CheckedLibs .= "<div class='lib_list'>\n";
15411 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15412 {
15413 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15414 $CheckedLibs .= $Library."<br/>\n";
15415 }
15416 $CheckedLibs .= "</div>\n";
15417 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015418 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015419
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015420 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15421}
15422
15423sub get_ObjTitle()
15424{
15425 if(defined $UsedDump{1}{"DWARF"}) {
15426 return "Objects";
15427 }
15428 else {
15429 return ucfirst($SLIB_TYPE)." Libraries";
15430 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015431}
15432
15433sub get_TypeProblems_Count($$$)
15434{
15435 my ($TypeChanges, $TargetPriority, $Level) = @_;
15436 my $Type_Problems_Count = 0;
15437 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15438 {
15439 my %Kinds_Target = ();
15440 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15441 {
15442 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15443 {
15444 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015445 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15446 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015447 if($Kinds_Target{$Kind}{$Target}) {
15448 next;
15449 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015450
15451 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15452 {
15453 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15454 { # select a problem with the highest priority
15455 next;
15456 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015457 }
15458 $Kinds_Target{$Kind}{$Target} = 1;
15459 $Type_Problems_Count += 1;
15460 }
15461 }
15462 }
15463 return $Type_Problems_Count;
15464}
15465
15466sub get_Summary($)
15467{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015468 my $Level = $_[0];
15469 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015470 $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 +040015471 %{$RESULT{$Level}} = (
15472 "Problems"=>0,
15473 "Warnings"=>0,
15474 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015475 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015476 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015477 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015478 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015479 {
15480 if(not defined $CompatRules{$Level}{$Kind})
15481 { # unknown rule
15482 if(not $UnknownRules{$Level}{$Kind})
15483 { # only one warning
15484 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15485 $UnknownRules{$Level}{$Kind}=1;
15486 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015487 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015488 }
15489 }
15490 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015491 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15492 {
15493 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15494 {
15495 if(not defined $CompatRules{$Level}{$Kind})
15496 { # unknown rule
15497 if(not $UnknownRules{$Level}{$Kind})
15498 { # only one warning
15499 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15500 $UnknownRules{$Level}{$Kind}=1;
15501 }
15502 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15503 }
15504 }
15505 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015506 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015507 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015508 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015509 {
15510 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15511 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015512 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015513 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015514 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015515 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015516 $Added += 1;
15517 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015518 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015519 {
15520 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015521 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015522 }
15523 else
15524 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015525 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015526 $I_Other += 1;
15527 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015528 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015529 $I_Problems_High += 1;
15530 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015531 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015532 $I_Problems_Medium += 1;
15533 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015534 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015535 $I_Problems_Low += 1;
15536 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015537 if(($Severity ne "Low" or $StrictCompat)
15538 and $Severity ne "Safe") {
15539 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015540 }
15541 }
15542 }
15543 }
15544 }
15545 }
15546 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015547 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015548 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015549 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015550 {
15551 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15552 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015553 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015554 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015555 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15556 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015557 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015558 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15559
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015560 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015561 { # select a problem with the highest priority
15562 next;
15563 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015564
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015565 if(($Severity ne "Low" or $StrictCompat)
15566 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015567 {
15568 if(defined $TotalAffected{$Level}{$Interface})
15569 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015570 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15571 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015572 }
15573 }
15574 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015575 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015577 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015578
15579 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15580
15581 if($MaxSeverity)
15582 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015583 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15584 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015585 }
15586 }
15587 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015588 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015590 }
15591 }
15592 }
15593 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015594
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015595 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15596 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15597 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15598 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015599
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015600 %TypeChanges = (); # free memory
15601
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015602 # changed and removed public symbols
15603 my $SCount = keys(%{$CheckedSymbols{$Level}});
15604 if($ExtendedCheck)
15605 { # don't count external_func_0 for constants
15606 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015607 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015608 if($SCount)
15609 {
15610 my %Weight = (
15611 "High" => 100,
15612 "Medium" => 50,
15613 "Low" => 25
15614 );
15615 foreach (keys(%{$TotalAffected{$Level}})) {
15616 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015617 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015618 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015619 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015620 else {
15621 $RESULT{$Level}{"Affected"} = 0;
15622 }
15623
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015624 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15625 if($RESULT{$Level}{"Affected"}>=100) {
15626 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015627 }
15628
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015629 $RESULT{$Level}{"Problems"} += $Removed;
15630 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015631 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015632 if($StrictCompat) {
15633 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15634 }
15635 else {
15636 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15637 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015638
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015639 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015640 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015641 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015642 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015643 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015644 if($Severity eq "Safe")
15645 {
15646 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015647 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015648 elsif($Severity eq "Low")
15649 {
15650 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015651 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015652 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015653 }
15654
15655 if($C_Problems_Low)
15656 {
15657 if($StrictCompat) {
15658 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15659 }
15660 else {
15661 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015662 }
15663 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015664 if($RESULT{$Level}{"Problems"}
15665 and $RESULT{$Level}{"Affected"}) {
15666 $RESULT{$Level}{"Verdict"} = "incompatible";
15667 }
15668 else {
15669 $RESULT{$Level}{"Verdict"} = "compatible";
15670 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015671
15672 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15673 if(not $TotalTypes)
15674 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015675 $TotalTypes = keys(%{$TName_Tid{1}});
15676 }
15677
15678 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15679 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15680
15681 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15682
15683 if($ReportFormat eq "xml")
15684 { # XML
15685 # test info
15686 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15687 $TestInfo .= " <version1>\n";
15688 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015689 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015690 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15691 $TestInfo .= " </version1>\n";
15692
15693 $TestInfo .= " <version2>\n";
15694 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015695 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015696 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15697 $TestInfo .= " </version2>\n";
15698 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15699
15700 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015701 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015702 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015703 $TestResults .= " <headers>\n";
15704 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15705 {
15706 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15707 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15708 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15709 }
15710 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015711 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015712
15713 if(my @Sources = keys(%{$Registered_Sources{1}}))
15714 {
15715 $TestResults .= " <sources>\n";
15716 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15717 {
15718 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15719 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15720 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15721 }
15722 $TestResults .= " </sources>\n";
15723 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015724
15725 $TestResults .= " <libs>\n";
15726 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15727 {
15728 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15729 $TestResults .= " <name>$Library</name>\n";
15730 }
15731 $TestResults .= " </libs>\n";
15732
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015733 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015734 $TestResults .= " <types>".$TotalTypes."</types>\n";
15735
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015736 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15737 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015738 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15739
15740 # problem summary
15741 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15742 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15743
15744 $Problem_Summary .= " <problems_with_types>\n";
15745 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15746 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15747 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15748 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15749 $Problem_Summary .= " </problems_with_types>\n";
15750
15751 $Problem_Summary .= " <problems_with_symbols>\n";
15752 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15753 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15754 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015755 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015756 $Problem_Summary .= " </problems_with_symbols>\n";
15757
15758 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015759 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015760 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015761
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015762 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15763
15764 return ($TestInfo.$TestResults.$Problem_Summary, "");
15765 }
15766 else
15767 { # HTML
15768 # test info
15769 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015770 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015771 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetTitle</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015772
15773 my (@VInf1, @VInf2, $AddTestInfo) = ();
15774 if($Arch1 ne "unknown"
15775 and $Arch2 ne "unknown")
15776 { # CPU arch
15777 if($Arch1 eq $Arch2)
15778 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015779 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015780 }
15781 else
15782 { # go to the version number
15783 push(@VInf1, showArch($Arch1));
15784 push(@VInf2, showArch($Arch2));
15785 }
15786 }
15787 if($GccV1 ne "unknown"
15788 and $GccV2 ne "unknown"
15789 and $OStarget ne "windows")
15790 { # GCC version
15791 if($GccV1 eq $GccV2)
15792 { # go to the separate section
15793 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15794 }
15795 else
15796 { # go to the version number
15797 push(@VInf1, "gcc ".$GccV1);
15798 push(@VInf2, "gcc ".$GccV2);
15799 }
15800 }
15801 # show long version names with GCC version and CPU architecture name (if different)
15802 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15803 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15804 $TestInfo .= $AddTestInfo;
15805 #if($COMMON_LANGUAGE{1}) {
15806 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15807 #}
15808 if($ExtendedCheck) {
15809 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15810 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015811 if($JoinReport)
15812 {
15813 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015814 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015815 }
15816 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015817 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015818 }
15819 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015820 $TestInfo .= "</table>\n";
15821
15822 # test results
15823 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015824 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015825
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030015826 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015827 {
15828 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15829 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15830 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015831
15832 if(my @Sources = keys(%{$Registered_Sources{1}}))
15833 {
15834 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15835 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15836 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015837
15838 if(not $ExtendedCheck)
15839 {
15840 my $Libs_Link = "0";
15841 $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 +040015842 $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 +040015843 }
15844
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015845 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015846
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015847 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015848 if($JoinReport) {
15849 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15850 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015851 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015852 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015853 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15854 }
15855 else {
15856 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15857 }
15858 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015859 $TestResults .= "</table>\n";
15860
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015861 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015862 # problem summary
15863 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015864 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015865 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15866
15867 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015868 if($Added>0)
15869 {
15870 if($JoinReport) {
15871 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15872 }
15873 else {
15874 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15875 }
15876 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015877 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015878 $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 +040015879
15880 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015881 if($Removed>0)
15882 {
15883 if($JoinReport) {
15884 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15885 }
15886 else {
15887 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
15888 }
15889 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015890 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015891 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
15892 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015893
15894 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015895 $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 +040015896 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015897 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
15898 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015899
15900 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015901 $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 +040015902 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015903 $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 +040015904
15905 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015906 $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 +040015907 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015908 $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 +040015909
15910 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015911 $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 +040015912 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015913 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
15914 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015915
15916 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015917 $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 +040015918 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015919 $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 +040015920
15921 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015922 $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 +040015923 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015924 $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 +040015925
15926 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015927 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
15928 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015930 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015931 $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 +040015932
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015933 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015934 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015935 {
15936 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015937 $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 +040015938 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015939
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015940 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015941 {
15942 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015943 $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 +040015944 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015945
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015946 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015947 {
15948 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
15949 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
15950 }
15951
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015952 $META_DATA .= "tool_version:$TOOL_VERSION";
15953 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015954 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015955 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
15956 }
15957}
15958
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015959sub getStyle($$$)
15960{
15961 my ($Subj, $Act, $Num) = @_;
15962 my %Style = (
15963 "A"=>"new",
15964 "R"=>"failed",
15965 "S"=>"passed",
15966 "L"=>"warning",
15967 "M"=>"failed",
15968 "H"=>"failed"
15969 );
15970 if($Num>0) {
15971 return " class='".$Style{$Act}."'";
15972 }
15973 return "";
15974}
15975
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015976sub show_number($)
15977{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015978 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015979 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015980 my $Num = cut_off_number($_[0], 2, 0);
15981 if($Num eq "0")
15982 {
15983 foreach my $P (3 .. 7)
15984 {
15985 $Num = cut_off_number($_[0], $P, 1);
15986 if($Num ne "0") {
15987 last;
15988 }
15989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015990 }
15991 if($Num eq "0") {
15992 $Num = $_[0];
15993 }
15994 return $Num;
15995 }
15996 return $_[0];
15997}
15998
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015999sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016000{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016001 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016002 if($num!~/\./)
16003 {
16004 $num .= ".";
16005 foreach (1 .. $digs_to_cut-1) {
16006 $num .= "0";
16007 }
16008 }
16009 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16010 {
16011 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16012 $num .= "0";
16013 }
16014 }
16015 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16016 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16017 }
16018 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016019 if($z) {
16020 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016022 return $num;
16023}
16024
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016025sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016026{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016027 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016028 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016029
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016030 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016031 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16032 {
16033 my $Header = $Constants{1}{$Constant}{"Header"};
16034 if(not $Header)
16035 { # added
16036 $Header = $Constants{2}{$Constant}{"Header"}
16037 }
16038
16039 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16040 {
16041 if(not defined $CompatRules{$Level}{$Kind}) {
16042 next;
16043 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016044 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016045 next;
16046 }
16047 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16048 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016049 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016050
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016051 if($ReportFormat eq "xml")
16052 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016053 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016054 {
16055 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016056 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016057 {
16058 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016059 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16060 {
16061 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16062 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16063 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016064
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016065 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16066 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16067 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016068 if($Overcome) {
16069 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16070 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016071 $CHANGED_CONSTANTS .= " </problem>\n";
16072 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016073 $CHANGED_CONSTANTS .= " </constant>\n";
16074 }
16075 $CHANGED_CONSTANTS .= " </header>\n";
16076 }
16077 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16078 }
16079 else
16080 { # HTML
16081 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016082 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016083 {
16084 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016085 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016086 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016087 my $Report = "";
16088
16089 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16090 {
16091 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16092 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16093 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16094 $Number += 1;
16095 }
16096 if($Report)
16097 {
16098 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16099 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16100 $Report = insertIDs($Report);
16101 }
16102 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016103 }
16104 $CHANGED_CONSTANTS .= "<br/>\n";
16105 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016106 if($CHANGED_CONSTANTS)
16107 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016108 my $Title = "Problems with Constants, $TargetSeverity Severity";
16109 if($TargetSeverity eq "Safe")
16110 { # Safe Changes
16111 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016112 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016113 $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 +040016114 }
16115 }
16116 return $CHANGED_CONSTANTS;
16117}
16118
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016119sub getTitle($$$)
16120{
16121 my ($Header, $Library, $NameSpace) = @_;
16122 my $Title = "";
16123 if($Library and $Library!~/\.\w+\Z/) {
16124 $Library .= " (.$LIB_EXT)";
16125 }
16126 if($Header and $Library)
16127 {
16128 $Title .= "<span class='h_name'>$Header</span>";
16129 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16130 }
16131 elsif($Library) {
16132 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16133 }
16134 elsif($Header) {
16135 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16136 }
16137 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016138 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016139 }
16140 return $Title;
16141}
16142
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016143sub get_Report_Added($)
16144{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016145 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016146 my $ADDED_INTERFACES = "";
16147 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016148 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016149 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016150 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016151 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016152 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016153 {
16154 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16155 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016156 if($Level eq "Source" and $ReportFormat eq "html")
16157 { # do not show library name in HTML report
16158 $DyLib = "";
16159 }
16160 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016161 }
16162 }
16163 }
16164 if($ReportFormat eq "xml")
16165 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016166 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016167 {
16168 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016169 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016170 {
16171 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016172 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016173 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16174 }
16175 $ADDED_INTERFACES .= " </library>\n";
16176 }
16177 $ADDED_INTERFACES .= " </header>\n";
16178 }
16179 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16180 }
16181 else
16182 { # HTML
16183 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016184 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016185 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016186 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016187 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016188 my %NameSpaceSymbols = ();
16189 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016190 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016191 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016192 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016193 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016194 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16195 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016196 foreach my $Interface (@SortedInterfaces)
16197 {
16198 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016199 my $Signature = get_Signature($Interface, 2);
16200 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016201 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016202 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016203 if($Interface=~/\A(_Z|\?)/)
16204 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016205 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016206 $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 +040016207 }
16208 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016209 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016210 }
16211 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016212 else
16213 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016214 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016215 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016216 }
16217 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016218 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016219 }
16220 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016221 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016222 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016223 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016224 }
16225 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016226 if($ADDED_INTERFACES)
16227 {
16228 my $Anchor = "<a name='Added'></a>";
16229 if($JoinReport) {
16230 $Anchor = "<a name='".$Level."_Added'></a>";
16231 }
16232 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016233 }
16234 }
16235 return $ADDED_INTERFACES;
16236}
16237
16238sub get_Report_Removed($)
16239{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016240 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016241 my $REMOVED_INTERFACES = "";
16242 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016243 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016244 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016245 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016246 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016247 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016248 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016249 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16250 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016251 if($Level eq "Source" and $ReportFormat eq "html")
16252 { # do not show library name in HTML report
16253 $DyLib = "";
16254 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016255 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016256 }
16257 }
16258 }
16259 if($ReportFormat eq "xml")
16260 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016261 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016262 {
16263 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016264 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016265 {
16266 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016267 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16268 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016269 }
16270 $REMOVED_INTERFACES .= " </library>\n";
16271 }
16272 $REMOVED_INTERFACES .= " </header>\n";
16273 }
16274 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16275 }
16276 else
16277 { # HTML
16278 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016279 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016280 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016281 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016282 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016283 my %NameSpaceSymbols = ();
16284 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016285 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016286 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016287 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016288 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016289 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16290 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016291 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016292 {
16293 $Removed_Number += 1;
16294 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016295 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016296 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016297 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016298 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016299 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016300 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016301 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016302 $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 +040016303 }
16304 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016305 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016306 }
16307 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016308 else
16309 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016310 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016311 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016312 }
16313 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016314 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016315 }
16316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016317 }
16318 }
16319 $REMOVED_INTERFACES .= "<br/>\n";
16320 }
16321 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016322 if($REMOVED_INTERFACES)
16323 {
16324 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16325 if($JoinReport) {
16326 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16327 }
16328 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016329 }
16330 }
16331 return $REMOVED_INTERFACES;
16332}
16333
16334sub getXmlParams($$)
16335{
16336 my ($Content, $Problem) = @_;
16337 return "" if(not $Content or not $Problem);
16338 my %XMLparams = ();
16339 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16340 {
16341 my $Macro = "\@".lc($Attr);
16342 if($Content=~/\Q$Macro\E/) {
16343 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16344 }
16345 }
16346 my @PString = ();
16347 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016348 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016349 }
16350 if(@PString) {
16351 return " ".join(" ", @PString);
16352 }
16353 else {
16354 return "";
16355 }
16356}
16357
16358sub addMarkup($)
16359{
16360 my $Content = $_[0];
16361 # auto-markup
16362 $Content=~s/\n[ ]*//; # spaces
16363 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16364 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016365 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016366 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16367 if($Content=~/\ANOTE:/)
16368 { # notes
16369 $Content=~s!(NOTE):!<b>$1</b>:!g;
16370 }
16371 else {
16372 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16373 }
16374 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16375 my @Keywords = (
16376 "void",
16377 "const",
16378 "static",
16379 "restrict",
16380 "volatile",
16381 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016382 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016383 );
16384 my $MKeys = join("|", @Keywords);
16385 foreach (@Keywords) {
16386 $MKeys .= "|non-".$_;
16387 }
16388 $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 +040016389
16390 # Markdown
16391 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16392 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016393 return $Content;
16394}
16395
16396sub applyMacroses($$$$)
16397{
16398 my ($Level, $Kind, $Content, $Problem) = @_;
16399 return "" if(not $Content or not $Problem);
16400 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16401 $Content = addMarkup($Content);
16402 # macros
16403 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16404 {
16405 my $Macro = "\@".lc($Attr);
16406 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016407 if(not defined $Value
16408 or $Value eq "") {
16409 next;
16410 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016411
16412 if(index($Content, $Macro)==-1) {
16413 next;
16414 }
16415
16416 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16417 and $Kind!~/_Type_/
16418 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016419 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016420 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016421 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016422 $Value = black_name($Value);
16423 }
16424 elsif($Value=~/\s/) {
16425 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16426 }
16427 elsif($Value=~/\A\d+\Z/
16428 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16429 { # bits to bytes
16430 if($Value % $BYTE_SIZE)
16431 { # bits
16432 if($Value==1) {
16433 $Value = "<b>".$Value."</b> bit";
16434 }
16435 else {
16436 $Value = "<b>".$Value."</b> bits";
16437 }
16438 }
16439 else
16440 { # bytes
16441 $Value /= $BYTE_SIZE;
16442 if($Value==1) {
16443 $Value = "<b>".$Value."</b> byte";
16444 }
16445 else {
16446 $Value = "<b>".$Value."</b> bytes";
16447 }
16448 }
16449 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016450 else
16451 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016452 $Value = "<b>".htmlSpecChars($Value)."</b>";
16453 }
16454 $Content=~s/\Q$Macro\E/$Value/g;
16455 }
16456
16457 if($Content=~/(\A|[^\@\w])\@\w/)
16458 {
16459 if(not $IncompleteRules{$Level}{$Kind})
16460 { # only one warning
16461 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16462 $IncompleteRules{$Level}{$Kind} = 1;
16463 }
16464 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016465 return $Content;
16466}
16467
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016468sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016469{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016470 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016471 my $INTERFACE_PROBLEMS = "";
16472 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016473
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016474 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016475 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016476 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16477 if($SV and defined $CompatProblems{$Level}{$SN}) {
16478 next;
16479 }
16480 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016481 {
16482 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016483 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016484 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016485 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16486 my $DyLib = $Symbol_Library{1}{$Symbol};
16487 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016488 { # Symbol with Version
16489 $DyLib = $Symbol_Library{1}{$VSym};
16490 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016491 if(not $DyLib)
16492 { # const global data
16493 $DyLib = "";
16494 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016495 if($Level eq "Source" and $ReportFormat eq "html")
16496 { # do not show library name in HTML report
16497 $DyLib = "";
16498 }
16499 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16500 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016501 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016502 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16503 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016504 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016505 }
16506 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016507 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16508 {
16509 delete($SymbolChanges{$Symbol}{$Kind});
16510 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016511 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016512 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016513 }
16514 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016515 if(not keys(%{$SymbolChanges{$Symbol}})) {
16516 delete($SymbolChanges{$Symbol});
16517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016518 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016519
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016520 if($ReportFormat eq "xml")
16521 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016522 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016523 {
16524 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016525 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016526 {
16527 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016528 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16529 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016530 {
16531 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16532 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16533 {
16534 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16535 {
16536 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016537 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016538
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016539 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16540 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16541 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16542 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16543 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016544 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16545 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16546 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016547 $INTERFACE_PROBLEMS .= " </problem>\n";
16548 }
16549 }
16550 $INTERFACE_PROBLEMS .= " </symbol>\n";
16551 }
16552 $INTERFACE_PROBLEMS .= " </library>\n";
16553 }
16554 $INTERFACE_PROBLEMS .= " </header>\n";
16555 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016556 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016557 }
16558 else
16559 { # HTML
16560 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016561 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016562 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016563 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016564 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016565 my (%NameSpaceSymbols, %NewSignature) = ();
16566 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016567 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016568 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016569 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016570 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016571 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016572 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} sort keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016573 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016574 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016575 my $Signature = get_Signature($Symbol, 1);
16576 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016577 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016578 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016579 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016580 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016581 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016582 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016583 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016584 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016585 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016586 }
16587 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16588 {
16589 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016590 $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 +040016591 $ProblemNum += 1;
16592 $ProblemsNum += 1;
16593 }
16594 }
16595 }
16596 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016597 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016598 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016599 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016600 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016601 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016602 }
16603 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016604 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016605 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016606 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16607 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16608 if($NewSignature{$Symbol})
16609 { # argument list changed to
16610 $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 +040016611 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016612 if($Symbol=~/\A(_Z|\?)/) {
16613 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16614 }
16615 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16616 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016617 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016618 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016619 }
16620 }
16621 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016622 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016623 }
16624 }
16625 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016626
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016627 if($INTERFACE_PROBLEMS)
16628 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016629 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16630 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16631 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016632 { # Safe Changes
16633 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016634 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016635 $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 +040016636 }
16637 }
16638 return $INTERFACE_PROBLEMS;
16639}
16640
16641sub get_Report_TypeProblems($$)
16642{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016643 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016644 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016645 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016646
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016647 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016648 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016649 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016650 {
16651 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16652 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016653 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016654 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016655 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016656 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016657 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016658
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016659 if($Severity eq "Safe"
16660 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016661 next;
16662 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016663
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016664 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16665 {
16666 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16667 { # select a problem with the highest priority
16668 next;
16669 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016670 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016671
16672 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016673 }
16674 }
16675 }
16676 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016677
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016678 my %Kinds_Locations = ();
16679 foreach my $TypeName (keys(%TypeChanges))
16680 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016681 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016682 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16683 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016684 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016685 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016686 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016687 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016688 { # other priority
16689 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16690 next;
16691 }
16692 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16693 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016694 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016695 { # duplicate target
16696 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16697 next;
16698 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016699 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016700 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016701 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016702 }
16703 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16704 delete($TypeChanges{$TypeName}{$Kind});
16705 }
16706 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016707 if(not keys(%{$TypeChanges{$TypeName}})) {
16708 delete($TypeChanges{$TypeName});
16709 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016710 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016711
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016712 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 +040016713 if($ReportFormat eq "xml")
16714 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016715 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016716 {
16717 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016718 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016719 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016720 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016721 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16722 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016723 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016724 {
16725 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16726 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16727 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16728 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16729 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16730 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016731 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16732 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016734 $TYPE_PROBLEMS .= " </problem>\n";
16735 }
16736 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016737 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016738 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016739 $TYPE_PROBLEMS .= showVTables($TypeName);
16740 }
16741 $TYPE_PROBLEMS .= " </type>\n";
16742 }
16743 $TYPE_PROBLEMS .= " </header>\n";
16744 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016745 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016746 }
16747 else
16748 { # HTML
16749 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016750 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016751 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016752 my (%NameSpace_Type) = ();
16753 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016754 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016755 }
16756 foreach my $NameSpace (sort keys(%NameSpace_Type))
16757 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016758 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016759 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 +040016760 foreach my $TypeName (@SortedTypes)
16761 {
16762 my $ProblemNum = 1;
16763 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016764
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016765 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16766 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016767 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016768 {
16769 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16770 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16771 {
16772 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
16773 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16774 $ProblemNum += 1;
16775 $ProblemsNum += 1;
16776 }
16777 }
16778 }
16779 $ProblemNum -= 1;
16780 if($TYPE_REPORT)
16781 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016782 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016783 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016784 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016785 $ShowVTables = showVTables($TypeName);
16786 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016787
16788 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016789 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16790 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16791 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16792 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016793 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016794 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016795 }
16796 }
16797 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016798 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016799 }
16800 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016801
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016802 if($TYPE_PROBLEMS)
16803 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016804 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16805 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016806 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016807 { # Safe Changes
16808 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016809 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016810 $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 +040016811 }
16812 }
16813 return $TYPE_PROBLEMS;
16814}
16815
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016816sub show_Type($$$)
16817{
16818 my ($Name, $Html, $LibVersion) = @_;
16819 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16820 $TType = lc($TType);
16821 if($TType=~/struct|union|enum/) {
16822 $Name=~s/\A\Q$TType\E //g;
16823 }
16824 if($Html) {
16825 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16826 }
16827 else {
16828 $Name = $TType." ".$Name;
16829 }
16830 return $Name;
16831}
16832
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016833sub get_Anchor($$$)
16834{
16835 my ($Kind, $Level, $Severity) = @_;
16836 if($JoinReport)
16837 {
16838 if($Severity eq "Safe") {
16839 return "Other_".$Level."_Changes_In_".$Kind."s";
16840 }
16841 else {
16842 return $Kind."_".$Level."_Problems_".$Severity;
16843 }
16844 }
16845 else
16846 {
16847 if($Severity eq "Safe") {
16848 return "Other_Changes_In_".$Kind."s";
16849 }
16850 else {
16851 return $Kind."_Problems_".$Severity;
16852 }
16853 }
16854}
16855
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016856sub showVTables($)
16857{
16858 my $TypeName = $_[0];
16859 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016860 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016861 if(defined $Type1{"VTable"}
16862 and keys(%{$Type1{"VTable"}}))
16863 {
16864 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016865 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016866 if(defined $Type2{"VTable"}
16867 and keys(%{$Type2{"VTable"}}))
16868 {
16869 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
16870 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016871 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016872 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016873 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
16874 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016875 }
16876 my $VTABLES = "";
16877 if($ReportFormat eq "xml")
16878 { # XML
16879 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016880 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016881 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016882 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016883 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
16884 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016885 $VTABLES .= " </entry>\n";
16886 }
16887 $VTABLES .= " </vtable>\n\n";
16888 }
16889 else
16890 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016891 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016892 $VTABLES .= "<tr><th>Offset</th>";
16893 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016894 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016895 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016896 {
16897 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016898 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016899 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016900 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016901 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016902 $Color1 = " class='failed'";
16903 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016904 }
16905 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016906 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016907 }
16908 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016909 $VTABLES .= "<tr><th>".$Index."</th>\n";
16910 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
16911 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016912 }
16913 $VTABLES .= "</table><br/>\n";
16914 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016915 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016916 }
16917 return $VTABLES;
16918 }
16919 }
16920 return "";
16921}
16922
16923sub simpleVEntry($)
16924{
16925 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016926 if(not defined $VEntry
16927 or $VEntry eq "") {
16928 return "";
16929 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016930
16931 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016932 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
16933 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
16934 if($VEntry=~/\A_ZThn.+\Z/) {
16935 $VEntry = "non-virtual thunk";
16936 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016937 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016938 # support for old GCC versions
16939 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
16940 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
16941 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016942 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
16943 return $VEntry;
16944}
16945
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016946sub adjustParamPos($$$)
16947{
16948 my ($Pos, $Symbol, $LibVersion) = @_;
16949 if(defined $CompleteSignature{$LibVersion}{$Symbol})
16950 {
16951 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
16952 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
16953 {
16954 return $Pos-1;
16955 }
16956
16957 return $Pos;
16958 }
16959
16960 return undef;
16961}
16962
16963sub getParamPos($$$)
16964{
16965 my ($Name, $Symbol, $LibVersion) = @_;
16966
16967 if(defined $CompleteSignature{$LibVersion}{$Symbol}
16968 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
16969 {
16970 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
16971 foreach (keys(%{$Info->{"Param"}}))
16972 {
16973 if($Info->{"Param"}{$_}{"name"} eq $Name)
16974 {
16975 return $_;
16976 }
16977 }
16978 }
16979
16980 return undef;
16981}
16982
16983sub getParamName($)
16984{
16985 my $Loc = $_[0];
16986 $Loc=~s/\->.*//g;
16987 return $Loc;
16988}
16989
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016990sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016991{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016992 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016993 my $LIMIT = 10;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016994
16995 if(defined $AffectLimit)
16996 {
16997 $LIMIT = $AffectLimit;
16998 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016999
17000 my %SymSel = ();
17001 my %SymLocKind = ();
17002
17003 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017004 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017005 if(index($Symbol, "_Z")==0
17006 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017007 { # duplicated problems for C2 constructors, D2 and D0 destructors
17008 next;
17009 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017010
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017011 foreach my $Kind (sort keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017012 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017013 if(not defined $CompatProblems{$Level}{$Symbol}
17014 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17015 next;
17016 }
17017
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017018 foreach my $Loc (sort keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017019 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017020 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017021 next;
17022 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017023
17024 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17025 if($Level eq "Source")
17026 { # remove symbol version
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017027 $Symbol = $SN;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017028 }
17029
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017030 if($SV and defined $CompatProblems{$Level}{$SN}
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017031 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017032 { # duplicated problems for versioned symbols
17033 next;
17034 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017035
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017036 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017037 if($Type_Name ne $Target_TypeName) {
17038 next;
17039 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017040
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017041 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017042 }
17043 }
17044 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017045
17046 foreach my $Symbol (sort keys(%SymLocKind))
17047 {
17048 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17049 {
17050 foreach my $Kind (keys(%{$SymLocKind{$Symbol}{$Loc}}))
17051 {
17052 $SymSel{$Symbol}{"Loc"} = $Loc;
17053 $SymSel{$Symbol}{"Kind"} = $Kind;
17054
17055 last LOOP;
17056 }
17057 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017058 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017059
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017060 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017061 my $Num = 0;
17062
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017063 if($ReportFormat eq "xml")
17064 { # XML
17065 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017066
17067 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017068 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017069 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017070 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017071 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017072
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017073 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017074 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017075 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017076 $Target .= " param=\"$PName\"";
17077 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017078 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017079 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017080 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017081 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017082 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017083 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017084 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017085
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017086 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017087 $Target .= " field=\"$1\"";
17088 }
17089
17090 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017091 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017092 $Affected .= " </symbol>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017093
17094 if($Num>$LIMIT) {
17095 last LOOP;
17096 }
17097
17098 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017099 }
17100 $Affected .= " </affected>\n";
17101 }
17102 else
17103 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017104 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017105 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017106 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17107 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017108 my $PName = getParamName($SymSel{$Symbol}{"Loc"});
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017109 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17110
17111 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>";
17112 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
17113
17114 if($Num>$LIMIT) {
17115 last;
17116 }
17117
17118 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017119 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017120
17121 if(keys(%SymSel)>$LIMIT) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017122 $Affected .= " ...<br/>"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017123 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017124
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017125 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017126 if($Affected)
17127 {
17128 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017129 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymSel).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017130 }
17131 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017132
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017133 return $Affected;
17134}
17135
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017136sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017137{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017138 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017139 if($L2=~/\A(retval|this)\b/
17140 and $L1!~/\A(retval|this)\b/)
17141 {
17142 if($L1!~/\-\>/) {
17143 return 1;
17144 }
17145 elsif($L2=~/\-\>/) {
17146 return 1;
17147 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017148 }
17149 return 0;
17150}
17151
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017152sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017153{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017154 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017155
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017156 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017157
17158 my $Location_I = $Location;
17159 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17160
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017161 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017162
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017163 if($Kind eq "Overridden_Virtual_Method"
17164 or $Kind eq "Overridden_Virtual_Method_B") {
17165 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17166 }
17167 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17168 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017169 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17170
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017171 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17172 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017173 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17174 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17175
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017176 if($ClassName eq $Problem{"Type_Name"}) {
17177 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17178 }
17179 else {
17180 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17181 }
17182 }
17183 else
17184 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017185 my $TypeID = undef;
17186
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017187 if($Location=~/retval/)
17188 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017189 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017190 push(@Sentence, "Field \'".$Location."\' in return value");
17191 }
17192 else {
17193 push(@Sentence, "Return value");
17194 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017195
17196 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017197 }
17198 elsif($Location=~/this/)
17199 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017200 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017201 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17202 }
17203 else {
17204 push(@Sentence, "\'this\' pointer");
17205 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017206
17207 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017208 }
17209 else
17210 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017211
17212 my $PName = getParamName($Location);
17213 my $PPos = getParamPos($PName, $Symbol, 1);
17214
17215 if(index($Location, "->")!=-1) {
17216 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017217 }
17218 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017219 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017220 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017221 if($PName) {
17222 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017223 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017224
17225 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17226 }
17227
17228 if($Location!~/this/)
17229 {
17230 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017231 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017232 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017233 push(@Sentence, "(pointer)");
17234 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017235 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017236 push(@Sentence, "(reference)");
17237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017238 }
17239 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017240
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017241 if($Location eq "this") {
17242 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17243 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017244 else
17245 {
17246 my $Location_T = $Location;
17247 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17248
17249 my $TypeID_Problem = $TypeID;
17250 if($Location_T) {
17251 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17252 }
17253
17254 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17255 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17256 }
17257 else {
17258 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017260 }
17261 }
17262 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017263 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017264 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 +040017265 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017266
17267 my $Sent = join(" ", @Sentence);
17268
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017269 $Sent=~s/->/./g;
17270
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017271 if($ReportFormat eq "xml")
17272 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017273 $Sent=~s/'//g;
17274 }
17275
17276 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017277}
17278
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017279sub getFieldType($$$)
17280{
17281 my ($Location, $TypeId, $LibVersion) = @_;
17282
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017283 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017284
17285 foreach my $Name (@Fields)
17286 {
17287 my %Info = get_BaseType($TypeId, $LibVersion);
17288
17289 foreach my $Pos (keys(%{$Info{"Memb"}}))
17290 {
17291 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17292 {
17293 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17294 last;
17295 }
17296 }
17297 }
17298
17299 return $TypeId;
17300}
17301
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017302sub get_XmlSign($$)
17303{
17304 my ($Symbol, $LibVersion) = @_;
17305 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17306 my $Report = "";
17307 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17308 {
17309 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017310 my $Type = $Info->{"Param"}{$Pos}{"type"};
17311 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017312 foreach my $Typedef (keys(%ChangedTypedef))
17313 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017314 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17315 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017317 }
17318 $Report .= " <param pos=\"$Pos\">\n";
17319 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017320 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017321 $Report .= " </param>\n";
17322 }
17323 if(my $Return = $Info->{"Return"})
17324 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017325 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017326 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017327 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017328 $Report .= " </retval>\n";
17329 }
17330 return $Report;
17331}
17332
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017333sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017334{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017335 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017336 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017337 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017338 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017339 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17340 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017341 next;
17342 }
17343 $Report .= " <symbol name=\"$Symbol\">\n";
17344 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017345 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017346 {
17347 if(defined $CompleteSignature{1}{$Symbol}
17348 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17349 {
17350 $P1 = get_XmlSign($Symbol, 1);
17351 $S1 = get_Signature($Symbol, 1);
17352 }
17353 elsif($Symbol=~/\A(_Z|\?)/) {
17354 $S1 = $tr_name{$Symbol};
17355 }
17356 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017357 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017358 {
17359 if(defined $CompleteSignature{2}{$Symbol}
17360 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17361 {
17362 $P2 = get_XmlSign($Symbol, 2);
17363 $S2 = get_Signature($Symbol, 2);
17364 }
17365 elsif($Symbol=~/\A(_Z|\?)/) {
17366 $S2 = $tr_name{$Symbol};
17367 }
17368 }
17369 if($S1)
17370 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017371 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017372 $Report .= $P1;
17373 $Report .= " </old>\n";
17374 }
17375 if($S2 and $S2 ne $S1)
17376 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017377 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017378 $Report .= $P2;
17379 $Report .= " </new>\n";
17380 }
17381 $Report .= " </symbol>\n";
17382 }
17383 $Report .= "</symbols_info>\n";
17384 return $Report;
17385}
17386
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017387sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017388{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017389 my ($Level, $Report) = @_;
17390 if($ReportFormat eq "xml") {
17391 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017392 }
17393 if($StdOut)
17394 { # --stdout option
17395 print STDOUT $Report;
17396 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017397 else
17398 {
17399 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017400 mkpath(get_dirname($RPath));
17401
17402 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17403 print REPORT $Report;
17404 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017405 }
17406}
17407
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017408sub getReport($)
17409{
17410 my $Level = $_[0];
17411 if($ReportFormat eq "xml")
17412 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017413 if($Level eq "Join")
17414 {
17415 my $Report = "<reports>\n";
17416 $Report .= getReport("Binary");
17417 $Report .= getReport("Source");
17418 $Report .= "</reports>\n";
17419 return $Report;
17420 }
17421 else
17422 {
17423 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17424 my ($Summary, $MetaData) = get_Summary($Level);
17425 $Report .= $Summary."\n";
17426 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17427 $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 +040017428
17429 # additional symbols info (if needed)
17430 # $Report .= get_Report_SymbolsInfo($Level);
17431
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017432 $Report .= "</report>\n";
17433 return $Report;
17434 }
17435 }
17436 else
17437 { # HTML
17438 my $CssStyles = readModule("Styles", "Report.css");
17439 my $JScripts = readModule("Scripts", "Sections.js");
17440 if($Level eq "Join")
17441 {
17442 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17443 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017444 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
17445 my $Keywords = $TargetTitle.", compatibility, API, report";
17446 my $Description = "Compatibility report for the $TargetTitle $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017447 my ($BSummary, $BMetaData) = get_Summary("Binary");
17448 my ($SSummary, $SMetaData) = get_Summary("Source");
17449 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 +030017450 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017451 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017452 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17453 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017454 </div>";
17455 $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>";
17456 $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 +030017457 $Report .= getReportFooter("Double");
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017458 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017459 return $Report;
17460 }
17461 else
17462 {
17463 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017464 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17465 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17466 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 +040017467 if($Level eq "Binary")
17468 {
17469 if(getArch(1) eq getArch(2)
17470 and getArch(1) ne "unknown") {
17471 $Description .= " on ".showArch(getArch(1));
17472 }
17473 }
17474 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 +030017475 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017476 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17477 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17478 $Report .= get_SourceInfo();
17479 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017480 $Report .= getReportFooter("Single");
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017481 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017482 return $Report;
17483 }
17484 }
17485}
17486
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017487sub getLegend()
17488{
17489 return "<br/>
17490<table class='summary'>
17491<tr>
17492 <td class='new'>added</td>
17493 <td class='passed'>compatible</td>
17494</tr>
17495<tr>
17496 <td class='warning'>warning</td>
17497 <td class='failed'>incompatible</td>
17498</tr></table>\n";
17499}
17500
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017501sub createReport()
17502{
17503 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017504 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017505 writeReport("Join", getReport("Join"));
17506 }
17507 elsif($DoubleReport)
17508 { # default
17509 writeReport("Binary", getReport("Binary"));
17510 writeReport("Source", getReport("Source"));
17511 }
17512 elsif($BinaryOnly)
17513 { # --binary
17514 writeReport("Binary", getReport("Binary"));
17515 }
17516 elsif($SourceOnly)
17517 { # --source
17518 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017519 }
17520}
17521
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017522sub getReportFooter($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017523{
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017524 my $Type = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017525 my $Class = "footer";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017526
17527 if($Type eq "Double") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017528 $Class .= " double_report";
17529 }
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017530
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017531 my $Footer = "<div class=\'$Class\' align='right'><i>Generated on ".(localtime time);
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017532 $Footer .= " by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017533 $Footer .= "</i></div>";
17534 $Footer .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017535 return $Footer;
17536}
17537
17538sub get_Report_Problems($$)
17539{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017540 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017541
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017542 my $Report = get_Report_TypeProblems($Severity, $Level);
17543 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017544 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017545 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017546
17547 if($Severity eq "Low" or $Severity eq "Safe") {
17548 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017549 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017550
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017551 if($ReportFormat eq "html")
17552 {
17553 if($Report)
17554 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017555 if($JoinReport)
17556 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017557 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017558 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17559 }
17560 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017561 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017562 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017563 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017564 else
17565 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017566 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017567 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17568 }
17569 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017570 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017571 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017572 }
17573 }
17574 }
17575 return $Report;
17576}
17577
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017578sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017579{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017580 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17581 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17582 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17583 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017584 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17585 <meta name=\"keywords\" content=\"$Keywords\" />
17586 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017587 <title>
17588 $Title
17589 </title>
17590 <style type=\"text/css\">
17591 $Styles
17592 </style>
17593 <script type=\"text/javascript\" language=\"JavaScript\">
17594 <!--
17595 $Scripts
17596 -->
17597 </script>
17598 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017599}
17600
17601sub insertIDs($)
17602{
17603 my $Text = $_[0];
17604 while($Text=~/CONTENT_ID/)
17605 {
17606 if(int($Content_Counter)%2) {
17607 $ContentID -= 1;
17608 }
17609 $Text=~s/CONTENT_ID/c_$ContentID/;
17610 $ContentID += 1;
17611 $Content_Counter += 1;
17612 }
17613 return $Text;
17614}
17615
17616sub checkPreprocessedUnit($)
17617{
17618 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017619 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017620 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017621 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017622
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017623 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017624 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017625 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017626 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017627 chomp($Line);
17628 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017629 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017630 $CurHeader = path_format($1, $OSgroup);
17631 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017632 $CurClass = "";
17633
17634 if(index($CurHeader, $TMP_DIR)==0) {
17635 next;
17636 }
17637
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017638 if(substr($CurHeaderName, 0, 1) eq "<")
17639 { # <built-in>, <command-line>, etc.
17640 $CurHeaderName = "";
17641 $CurHeader = "";
17642 }
17643
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017644 if($ExtraInfo)
17645 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017646 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017647 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17648 }
17649 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017650 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017651 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017652 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017653 if($CurHeaderName)
17654 {
17655 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17656 and not $Registered_Headers{$Version}{$CurHeader})
17657 { # not a target
17658 next;
17659 }
17660 if(not is_target_header($CurHeaderName, 1)
17661 and not is_target_header($CurHeaderName, 2))
17662 { # user-defined header
17663 next;
17664 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017665 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017666 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017667
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017668 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017669 {
17670 my ($Name, $Value) = ($1, $2);
17671 if(not $Constants{$Version}{$Name}{"Access"})
17672 {
17673 $Constants{$Version}{$Name}{"Access"} = "public";
17674 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017675 if($CurHeaderName) {
17676 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17677 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017678 }
17679 }
17680 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17681 $Constants{$Version}{$1}{"Access"} = "private";
17682 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017683 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017684 else
17685 {
17686 if(defined $ExtraDump)
17687 {
17688 if($Line=~/(\w+)\s*\(/)
17689 { # functions
17690 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17691 }
17692 #elsif($Line=~/(\w+)\s*;/)
17693 #{ # data
17694 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17695 #}
17696 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17697 $CurClass = $2;
17698 }
17699 }
17700 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017701 }
17702 close(PREPROC);
17703 foreach my $Constant (keys(%{$Constants{$Version}}))
17704 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017705 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17706 {
17707 delete($Constants{$Version}{$Constant});
17708 next;
17709 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017710 if(not $ExtraDump and ($Constant=~/_h\Z/i
17711 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017712 { # skip
17713 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017714 }
17715 else {
17716 delete($Constants{$Version}{$Constant}{"Access"});
17717 }
17718 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017719 if($Debug)
17720 {
17721 mkpath($DEBUG_PATH{$Version});
17722 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17723 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017724}
17725
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017726sub uncoverConstant($$)
17727{
17728 my ($LibVersion, $Constant) = @_;
17729 return "" if(not $LibVersion or not $Constant);
17730 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17731 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17732 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17733 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017734
17735 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017736 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017737 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17738 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017739 {
17740 push(@RecurConstant, $Constant);
17741 my $Uncovered = uncoverConstant($LibVersion, $Value);
17742 if($Uncovered ne "") {
17743 $Value = $Uncovered;
17744 }
17745 pop(@RecurConstant);
17746 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017747
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017748 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017749 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017750 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17751 }
17752 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17753}
17754
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017755sub simpleConstant($$)
17756{
17757 my ($LibVersion, $Value) = @_;
17758 if($Value=~/\W/)
17759 {
17760 my $Value_Copy = $Value;
17761 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17762 {
17763 my $Word = $1;
17764 if($Value!~/$Word\s*\(/)
17765 {
17766 my $Val = uncoverConstant($LibVersion, $Word);
17767 if($Val ne "")
17768 {
17769 $Value=~s/\b$Word\b/$Val/g;
17770 }
17771 }
17772 }
17773 }
17774 return $Value;
17775}
17776
17777sub computeValue($)
17778{
17779 my $Value = $_[0];
17780
17781 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17782 return $1;
17783 }
17784
17785 if($Value=~/\A[\d\-\+()]+\Z/) {
17786 return eval($Value);
17787 }
17788
17789 return $Value;
17790}
17791
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017792my %IgnoreConstant = map {$_=>1} (
17793 "VERSION",
17794 "VERSIONCODE",
17795 "VERNUM",
17796 "VERS_INFO",
17797 "PATCHLEVEL",
17798 "INSTALLPREFIX",
17799 "VBUILD",
17800 "VPATCH",
17801 "VMINOR",
17802 "BUILD_STRING",
17803 "BUILD_TIME",
17804 "PACKAGE_STRING",
17805 "PRODUCTION",
17806 "CONFIGURE_COMMAND",
17807 "INSTALLDIR",
17808 "BINDIR",
17809 "CONFIG_FILE_PATH",
17810 "DATADIR",
17811 "EXTENSION_DIR",
17812 "INCLUDE_PATH",
17813 "LIBDIR",
17814 "LOCALSTATEDIR",
17815 "SBINDIR",
17816 "SYSCONFDIR",
17817 "RELEASE",
17818 "SOURCE_ID",
17819 "SUBMINOR",
17820 "MINOR",
17821 "MINNOR",
17822 "MINORVERSION",
17823 "MAJOR",
17824 "MAJORVERSION",
17825 "MICRO",
17826 "MICROVERSION",
17827 "BINARY_AGE",
17828 "INTERFACE_AGE",
17829 "CORE_ABI",
17830 "PATCH",
17831 "COPYRIGHT",
17832 "TIMESTAMP",
17833 "REVISION",
17834 "PACKAGE_TAG",
17835 "PACKAGEDATE",
17836 "NUMVERSION",
17837 "Release",
17838 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017839);
17840
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017841sub constantFilter($$$)
17842{
17843 my ($Name, $Value, $Level) = @_;
17844
17845 if($Level eq "Binary")
17846 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017847 if($Name=~/_t\Z/)
17848 { # __malloc_ptr_t
17849 return 1;
17850 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017851 foreach (keys(%IgnoreConstant))
17852 {
17853 if($Name=~/(\A|_)$_(_|\Z)/)
17854 { # version
17855 return 1;
17856 }
17857 if(/\A[A-Z].*[a-z]\Z/)
17858 {
17859 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17860 { # version
17861 return 1;
17862 }
17863 }
17864 }
17865 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17866 { # version
17867 return 1;
17868 }
17869 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17870 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17871 return 1;
17872 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017873
17874 if($Value=~/\A["'].*['"]/i)
17875 { # string
17876 return 0;
17877 }
17878
17879 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17880 { # static int gcry_pth_init
17881 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017882 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017883 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017884 return 1;
17885 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017886 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017887 { # foo(p)
17888 return 1;
17889 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017890 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017891 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017892 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017893 return 1;
17894 }
17895 }
17896
17897 return 0;
17898}
17899
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017900sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017901{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017902 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017903 foreach my $Constant (keys(%{$Constants{1}}))
17904 {
17905 if($SkipConstants{1}{$Constant})
17906 { # skipped by the user
17907 next;
17908 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017909
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017910 if(my $Header = $Constants{1}{$Constant}{"Header"})
17911 {
17912 if(not is_target_header($Header, 1)
17913 and not is_target_header($Header, 2))
17914 { # user-defined header
17915 next;
17916 }
17917 }
17918 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017919 next;
17920 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017921
17922 my $Old_Value = uncoverConstant(1, $Constant);
17923
17924 if(constantFilter($Constant, $Old_Value, $Level))
17925 { # separate binary and source problems
17926 next;
17927 }
17928
17929 if(not defined $Constants{2}{$Constant}{"Value"})
17930 { # removed
17931 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
17932 "Target"=>$Constant,
17933 "Old_Value"=>$Old_Value );
17934 next;
17935 }
17936
17937 if($Constants{2}{$Constant}{"Value"} eq "")
17938 { # empty value
17939 # TODO: implement a rule
17940 next;
17941 }
17942
17943 my $New_Value = uncoverConstant(2, $Constant);
17944
17945 my $Old_Value_Pure = $Old_Value;
17946 my $New_Value_Pure = $New_Value;
17947
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017948 $Old_Value_Pure=~s/(\W)\s+/$1/g;
17949 $Old_Value_Pure=~s/\s+(\W)/$1/g;
17950 $New_Value_Pure=~s/(\W)\s+/$1/g;
17951 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017952
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017953 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017954
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017955 if($New_Value_Pure ne $Old_Value_Pure)
17956 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017957 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
17958 { # complex values
17959 next;
17960 }
17961 if(computeValue($Old_Value) eq computeValue($New_Value))
17962 { # expressions
17963 next;
17964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017965 if(convert_integer($Old_Value) eq convert_integer($New_Value))
17966 { # 0x0001 and 0x1, 0x1 and 1 equal constants
17967 next;
17968 }
17969 if($Old_Value eq "0" and $New_Value eq "NULL")
17970 { # 0 => NULL
17971 next;
17972 }
17973 if($Old_Value eq "NULL" and $New_Value eq "0")
17974 { # NULL => 0
17975 next;
17976 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017977 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017978 "Target"=>$Constant,
17979 "Old_Value"=>$Old_Value,
17980 "New_Value"=>$New_Value );
17981 }
17982 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017983
17984 foreach my $Constant (keys(%{$Constants{2}}))
17985 {
17986 if(not defined $Constants{1}{$Constant}{"Value"})
17987 {
17988 if($SkipConstants{2}{$Constant})
17989 { # skipped by the user
17990 next;
17991 }
17992
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017993 if(my $Header = $Constants{2}{$Constant}{"Header"})
17994 {
17995 if(not is_target_header($Header, 1)
17996 and not is_target_header($Header, 2))
17997 { # user-defined header
17998 next;
17999 }
18000 }
18001 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018002 next;
18003 }
18004
18005 my $New_Value = uncoverConstant(2, $Constant);
18006 if(not defined $New_Value or $New_Value eq "") {
18007 next;
18008 }
18009
18010 if(constantFilter($Constant, $New_Value, $Level))
18011 { # separate binary and source problems
18012 next;
18013 }
18014
18015 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18016 "Target"=>$Constant,
18017 "New_Value"=>$New_Value );
18018 }
18019 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018020}
18021
18022sub convert_integer($)
18023{
18024 my $Value = $_[0];
18025 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018026 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018027 return hex($Value);
18028 }
18029 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018030 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018031 return oct($Value);
18032 }
18033 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018034 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018035 return oct($Value);
18036 }
18037 else {
18038 return $Value;
18039 }
18040}
18041
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018042sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018043{
18044 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018045 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018046 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018047 {
18048 if($LibVersion==1)
18049 {
18050 printMsg("WARNING", "checking headers only");
18051 $CheckHeadersOnly = 1;
18052 }
18053 else {
18054 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18055 }
18056 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018057
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018058 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018059 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018060 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018061
18062 if($CheckUndefined)
18063 {
18064 my %UndefinedLibs = ();
18065
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018066 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18067
18068 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018069 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018070 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018071 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018072 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018073 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018074 if($Symbol_Library{$LibVersion}{$Symbol}
18075 or $DepSymbol_Library{$LibVersion}{$Symbol})
18076 { # exported by target library
18077 next;
18078 }
18079 if(index($Symbol, '@')!=-1)
18080 { # exported default symbol version (@@)
18081 $Symbol=~s/\@/\@\@/;
18082 if($Symbol_Library{$LibVersion}{$Symbol}
18083 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18084 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018085 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018086 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018087 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18088 $UndefinedLibs{$Path} = 1;
18089 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018090 }
18091 }
18092 }
18093 if($ExtraInfo)
18094 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018095 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018096 {
18097 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018098 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018099 foreach (@Paths)
18100 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018101 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018102 my ($Dir, $Name) = separate_path($_);
18103
18104 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018105 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018106 }
18107
18108 $Name = parse_libname($Name, "name", $OStarget);
18109 $Name=~s/\Alib//;
18110
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018111 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018112 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018113
18114 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18115 {
18116 $LibString = " -L".esc($Dir).$LibString;
18117 }
18118
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018119 writeFile($ExtraInfo."/libs-string", $LibString);
18120 }
18121 }
18122 }
18123
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018124 if($ExtraInfo) {
18125 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18126 }
18127
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018128 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018129 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018130 if($#LibPaths!=-1)
18131 {
18132 if(not keys(%{$Symbol_Library{$LibVersion}}))
18133 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018134 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018135 printMsg("WARNING", "checking headers only");
18136 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018137 }
18138 }
18139 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018140
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018141 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018142 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018143}
18144
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018145my %Prefix_Lib_Map=(
18146 # symbols for autodetecting library dependencies (by prefix)
18147 "pthread_" => ["libpthread"],
18148 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18149 "cairo_" => ["libcairo"],
18150 "gtk_" => ["libgtk-x11-2.0"],
18151 "atk_" => ["libatk-1.0"],
18152 "gdk_" => ["libgdk-x11-2.0"],
18153 "gl" => ["libGL"],
18154 "glu" => ["libGLU"],
18155 "popt" => ["libpopt"],
18156 "Py" => ["libpython"],
18157 "jpeg_" => ["libjpeg"],
18158 "BZ2_" => ["libbz2"],
18159 "Fc" => ["libfontconfig"],
18160 "Xft" => ["libXft"],
18161 "SSL_" => ["libssl"],
18162 "sem_" => ["libpthread"],
18163 "snd_" => ["libasound"],
18164 "art_" => ["libart_lgpl_2"],
18165 "dbus_g" => ["libdbus-glib-1"],
18166 "GOMP_" => ["libgomp"],
18167 "omp_" => ["libgomp"],
18168 "cms" => ["liblcms"]
18169);
18170
18171my %Pattern_Lib_Map=(
18172 "SL[a-z]" => ["libslang"]
18173);
18174
18175my %Symbol_Lib_Map=(
18176 # symbols for autodetecting library dependencies (by name)
18177 "pow" => "libm",
18178 "fmod" => "libm",
18179 "sin" => "libm",
18180 "floor" => "libm",
18181 "cos" => "libm",
18182 "dlopen" => "libdl",
18183 "deflate" => "libz",
18184 "inflate" => "libz",
18185 "move_panel" => "libpanel",
18186 "XOpenDisplay" => "libX11",
18187 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018188 "clock_gettime" => "librt",
18189 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018190);
18191
18192sub find_SymbolLibs($$)
18193{
18194 my ($LibVersion, $Symbol) = @_;
18195
18196 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18197 { # debug symbols
18198 return ();
18199 }
18200
18201 my %Paths = ();
18202
18203 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18204 {
18205 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18206 $Paths{$Path} = 1;
18207 }
18208 }
18209
18210 if(my $SymbolPrefix = getPrefix($Symbol))
18211 {
18212 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18213 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18214 }
18215
18216 if(not keys(%Paths))
18217 {
18218 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18219 {
18220 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18221 {
18222 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18223 $Paths{$Path} = 1;
18224 }
18225 }
18226 }
18227 }
18228
18229 if(not keys(%Paths))
18230 {
18231 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18232 {
18233 if($Symbol=~/\A$Prefix/)
18234 {
18235 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18236 {
18237 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18238 $Paths{$Path} = 1;
18239 }
18240 }
18241 }
18242 }
18243 }
18244
18245 if(not keys(%Paths))
18246 {
18247 if($SymbolPrefix)
18248 { # try to find a library by symbol prefix
18249 if($SymbolPrefix eq "inotify" and
18250 index($Symbol, "\@GLIBC")!=-1)
18251 {
18252 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18253 $Paths{$Path} = 1;
18254 }
18255 }
18256 else
18257 {
18258 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18259 $Paths{$Path} = 1;
18260 }
18261 }
18262 }
18263 }
18264
18265 if(my @Paths = keys(%Paths)) {
18266 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18267 }
18268 }
18269 return keys(%Paths);
18270}
18271
18272sub get_LibPath_Prefix($$)
18273{
18274 my ($LibVersion, $Prefix) = @_;
18275
18276 $Prefix = lc($Prefix);
18277 $Prefix=~s/[_]+\Z//g;
18278
18279 foreach ("-2", "2", "-1", "1", "")
18280 { # libgnome-2.so
18281 # libxml2.so
18282 # libdbus-1.so
18283 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18284 return $Path;
18285 }
18286 }
18287 return "";
18288}
18289
18290sub getPrefix($)
18291{
18292 my $Str = $_[0];
18293 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18294 { # XmuValidArea: Xmu
18295 return $1;
18296 }
18297 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18298 { # snfReadFont: snf
18299 return $1;
18300 }
18301 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18302 { # XRRTimes: XRR
18303 return $1;
18304 }
18305 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18306 { # H5HF_delete: H5
18307 return $1;
18308 }
18309 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18310 { # alarm_event_add: alarm_
18311 return $1;
18312 }
18313 elsif($Str=~/\A(([a-z])\2{1,})/i)
18314 { # ffopen
18315 return $1;
18316 }
18317 return "";
18318}
18319
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018320sub getSymbolSize($$)
18321{ # size from the shared library
18322 my ($Symbol, $LibVersion) = @_;
18323 return 0 if(not $Symbol);
18324 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18325 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18326 {
18327 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18328 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18329 {
18330 if($Size<0) {
18331 return -$Size;
18332 }
18333 }
18334 }
18335 return 0;
18336}
18337
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018338sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018339{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18340 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018341 my ($Name, $Type) = @_;
18342
18343 # single
18344 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018345 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018346 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018347 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018348 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018349
18350 # double
18351 if($Name=~/$DEFAULT_STD_PARMS/)
18352 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018353 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018354 {
18355 my ($ShortName, $FuncParams) = split_Signature($Name);
18356
18357 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18358 {
18359 if(index($FParam, "<")!=-1)
18360 {
18361 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18362 my $FParam_N = canonifyName($FParam, "T");
18363 if($FParam_N ne $FParam) {
18364 $Name=~s/\Q$FParam\E/$FParam_N/g;
18365 }
18366 }
18367 }
18368 }
18369 elsif($Type eq "T")
18370 {
18371 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18372
18373 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018374 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018375 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018376 my $FParam = $TParams[0];
18377 foreach my $Pos (1 .. $#TParams)
18378 {
18379 my $TParam = $TParams[$Pos];
18380 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18381 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18382 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018383 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018384 }
18385 }
18386 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018387 if($Type eq "S") {
18388 return formatName($Name, "S");
18389 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018390 return $Name;
18391}
18392
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018393sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018394{
18395 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018396 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018397 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018398 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018399 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018400 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018401 next if($tr_name{$Symbol});
18402 $Symbol=~s/[\@\$]+(.*)\Z//;
18403 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018404 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018405 elsif(index($Symbol, "?")==0)
18406 {
18407 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018408 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018409 }
18410 else
18411 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018412 $tr_name{$Symbol} = $Symbol;
18413 $mangled_name_gcc{$Symbol} = $Symbol;
18414 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018415 }
18416 }
18417 if($#MnglNames1 > -1)
18418 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018419 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018420 foreach my $MnglName (@MnglNames1)
18421 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018422 if(my $Unmangled = pop(@UnmangledNames))
18423 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018424 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018425 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18426 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18427 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018428 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018429 and $tr_name{$MnglName}=~/vtable for (.+)/)
18430 { # bind class name and v-table symbol
18431 my $ClassName = $1;
18432 $ClassVTable{$ClassName} = $MnglName;
18433 $VTableClass{$MnglName} = $ClassName;
18434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018435 }
18436 }
18437 }
18438 if($#MnglNames2 > -1)
18439 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018440 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018441 foreach my $MnglName (@MnglNames2)
18442 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018443 if(my $Unmangled = pop(@UnmangledNames))
18444 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018445 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018446 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18447 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018448 }
18449 }
18450 return \%tr_name;
18451}
18452
18453sub link_symbol($$$)
18454{
18455 my ($Symbol, $RunWith, $Deps) = @_;
18456 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18457 return 1;
18458 }
18459 if($Deps eq "+Deps")
18460 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018461 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018462 return 1;
18463 }
18464 }
18465 return 0;
18466}
18467
18468sub link_symbol_internal($$$)
18469{
18470 my ($Symbol, $RunWith, $Where) = @_;
18471 return 0 if(not $Where or not $Symbol);
18472 if($Where->{$RunWith}{$Symbol})
18473 { # the exact match by symbol name
18474 return 1;
18475 }
18476 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18477 { # indirect symbol version, i.e.
18478 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018479 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018480 if($Where->{$RunWith}{$VSym}) {
18481 return 1;
18482 }
18483 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018484 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018485 if($Sym and $Ver)
18486 { # search for the symbol with the same version
18487 # or without version
18488 if($Where->{$RunWith}{$Sym})
18489 { # old: foo@v|foo@@v
18490 # new: foo
18491 return 1;
18492 }
18493 if($Where->{$RunWith}{$Sym."\@".$Ver})
18494 { # old: foo|foo@@v
18495 # new: foo@v
18496 return 1;
18497 }
18498 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18499 { # old: foo|foo@v
18500 # new: foo@@v
18501 return 1;
18502 }
18503 }
18504 return 0;
18505}
18506
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018507sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018508{
18509 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018510 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018511 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018512 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018513 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018514 my $NM = get_CmdPath("nm");
18515 if(not $NM) {
18516 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018517 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018518 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018519 while(<APP>)
18520 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018521 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018522 push(@Imported, $1);
18523 }
18524 }
18525 close(APP);
18526 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018527 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018528 {
18529 my $DumpBinCmd = get_CmdPath("dumpbin");
18530 if(not $DumpBinCmd) {
18531 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18532 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018533 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018534 while(<APP>)
18535 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018536 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18537 push(@Imported, $1);
18538 }
18539 }
18540 close(APP);
18541 }
18542 else
18543 {
18544 my $ReadelfCmd = get_CmdPath("readelf");
18545 if(not $ReadelfCmd) {
18546 exitStatus("Not_Found", "can't find \"readelf\"");
18547 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018548 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018549 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018550 while(<APP>)
18551 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018552 if(defined $symtab)
18553 { # do nothing with symtab
18554 if(index($_, "'.dynsym'")!=-1)
18555 { # dynamic table
18556 $symtab = undef;
18557 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018558 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018559 elsif(index($_, "'.symtab'")!=-1)
18560 { # symbol table
18561 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018562 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018563 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018564 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018565 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18566 if($Ndx eq "UND")
18567 { # only imported symbols
18568 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018569 }
18570 }
18571 }
18572 close(APP);
18573 }
18574 return @Imported;
18575}
18576
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018577my %ELF_BIND = map {$_=>1} (
18578 "WEAK",
18579 "GLOBAL"
18580);
18581
18582my %ELF_TYPE = map {$_=>1} (
18583 "FUNC",
18584 "IFUNC",
18585 "OBJECT",
18586 "COMMON"
18587);
18588
18589my %ELF_VIS = map {$_=>1} (
18590 "DEFAULT",
18591 "PROTECTED"
18592);
18593
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018594sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018595{ # read the line of 'readelf' output corresponding to the symbol
18596 my @Info = split(/\s+/, $_[0]);
18597 # Num: Value Size Type Bind Vis Ndx Name
18598 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018599 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018600 shift(@Info); # spaces
18601 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018602
18603 if($#Info==7)
18604 { # UND SYMBOL (N)
18605 if($Info[7]=~/\(\d+\)/) {
18606 pop(@Info);
18607 }
18608 }
18609
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018610 if($#Info!=6)
18611 { # other lines
18612 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018613 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018614 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018615 return () if(not defined $ELF_BIND{$Info[3]});
18616 return () if(not defined $ELF_VIS{$Info[4]});
18617 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18618 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18619 return ();
18620 }
18621 if($OStarget eq "symbian")
18622 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18623 if(index($Info[6], "_._.absent_export_")!=-1)
18624 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18625 return ();
18626 }
18627 $Info[6]=~s/\@.+//g; # remove version
18628 }
18629 if(index($Info[2], "0x") == 0)
18630 { # size == 0x3d158
18631 $Info[2] = hex($Info[2]);
18632 }
18633 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018634}
18635
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018636sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018637{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018638 my ($LibVersion, $Name) = @_;
18639 return "" if(not $LibVersion or not $Name);
18640 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18641 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018642 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018643 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18644}
18645
18646sub get_LibPath_I($$)
18647{
18648 my ($LibVersion, $Name) = @_;
18649 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018650 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018651 if(-f $Name)
18652 { # absolute path
18653 return $Name;
18654 }
18655 else
18656 { # broken
18657 return "";
18658 }
18659 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018660 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018661 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018662 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018663 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018664 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018665 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018666 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018667 }
18668 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18669 { # ldconfig default paths
18670 return $DefaultPath;
18671 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018672 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018673 { # search in default linker directories
18674 # and then in all system paths
18675 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018676 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018677 }
18678 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018679 if(not defined $Cache{"checkSystemFiles"}) {
18680 checkSystemFiles();
18681 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018682 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18683 return $AllObjects[0];
18684 }
18685 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18686 {
18687 if($ShortName ne $Name)
18688 { # FIXME: check this case
18689 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18690 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018691 }
18692 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018693 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018694 # can't find
18695 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018696}
18697
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018698sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018699{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018700 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18701 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018702
18703 my $Real_Path = realpath($Lib_Path);
18704
18705 if(not $Real_Path)
18706 { # broken link
18707 return ();
18708 }
18709
18710 my $Lib_Name = get_filename($Real_Path);
18711
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018712 if($ExtraInfo)
18713 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018714 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018715 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018716 }
18717
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018718 if($IsNeededLib)
18719 {
18720 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18721 return ();
18722 }
18723 }
18724 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018725 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018726
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018727 push(@RecurLib, $Lib_Name);
18728 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018729 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18730
18731 if(not $IsNeededLib)
18732 { # special cases: libstdc++ and libc
18733 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18734 {
18735 if($ShortName eq "libstdc++")
18736 { # libstdc++.so.6
18737 $STDCXX_TESTING = 1;
18738 }
18739 elsif($ShortName eq "libc")
18740 { # libc-2.11.3.so
18741 $GLIBC_TESTING = 1;
18742 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018743 }
18744 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018745 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018746 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018747 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018748 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018749 mkpath(get_dirname($DebugPath));
18750 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018751 if($OStarget eq "macos")
18752 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018753 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018754 if(not $NM) {
18755 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018756 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018757 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018758 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018759 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018760 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018761 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018762 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018763 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018764 else
18765 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018766 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018767 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018768 while(<LIB>)
18769 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018770 if($CheckUndefined)
18771 {
18772 if(not $IsNeededLib)
18773 {
18774 if(/ U _([\w\$]+)\s*\Z/)
18775 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018776 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018777 next;
18778 }
18779 }
18780 }
18781
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018782 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018783 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018784 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018785 if($IsNeededLib)
18786 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018787 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018788 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018789 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18790 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018791 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018792 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018793 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018794 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018795 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18796 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018797 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18798 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018799 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018800 setLanguage($LibVersion, "C++");
18801 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018802 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018803 }
18804 }
18805 }
18806 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018807
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018808 if($Deps)
18809 {
18810 if($LIB_TYPE eq "dynamic")
18811 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018812
18813 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018814 if(not $OtoolCmd) {
18815 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018816 }
18817
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018818 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18819 while(<LIB>)
18820 {
18821 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18822 and $1 ne $Lib_Path) {
18823 $NeededLib{$1} = 1;
18824 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018825 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018826 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018827 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018828 }
18829 }
18830 elsif($OStarget eq "windows")
18831 { # Windows *.dll, *.lib
18832 my $DumpBinCmd = get_CmdPath("dumpbin");
18833 if(not $DumpBinCmd) {
18834 exitStatus("Not_Found", "can't find \"dumpbin\"");
18835 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018836 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018837 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018838 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018839 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018840 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018841 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018842 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018843 else
18844 { # write to pipe
18845 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018846 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018847 while(<LIB>)
18848 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18849 # 1198 4AD SetThreadToken (forwarded to ...)
18850 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018851 # 1 0 00005B30 ??0?N = ... (with pdb)
18852 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018853 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018854 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018855 { # dynamic, static and forwarded symbols
18856 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018857 if($IsNeededLib)
18858 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018859 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018860 {
18861 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18862 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018864 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018865 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018866 {
18867 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18868 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018869 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18870 {
18871 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18872 setLanguage($LibVersion, "C++");
18873 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018874 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018875 }
18876 }
18877 }
18878 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018879
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018880 if($Deps)
18881 {
18882 if($LIB_TYPE eq "dynamic")
18883 { # dependencies
18884 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18885 while(<LIB>)
18886 {
18887 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
18888 and $1 ne $Lib_Path) {
18889 $NeededLib{path_format($1, $OSgroup)} = 1;
18890 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018891 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018892 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018893 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018894 }
18895 }
18896 else
18897 { # Unix; *.so, *.a
18898 # Symbian: *.dso, *.lib
18899 my $ReadelfCmd = get_CmdPath("readelf");
18900 if(not $ReadelfCmd) {
18901 exitStatus("Not_Found", "can't find \"readelf\"");
18902 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018903 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018904 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018905 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018906 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018907 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018908 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018909 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018910 else
18911 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018912 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018913 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018914 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018915 while(<LIB>)
18916 {
18917 if($LIB_TYPE eq "dynamic")
18918 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018919 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018920 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018921 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018922 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018923 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018924 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018925 # do nothing with symtab
18926 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018927 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018928 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018929 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018930 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018931 next;
18932 }
18933 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018934 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018935 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018936 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018937 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018938 if($CheckUndefined)
18939 {
18940 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018941 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018942 }
18943 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018944 next;
18945 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040018946 if($Bind eq "WEAK")
18947 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018948 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040018949 if($Weak eq "-Weak")
18950 { # skip WEAK symbols
18951 next;
18952 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018953 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018954 my $Short = $Symbol;
18955 $Short=~s/\@.+//g;
18956 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018957 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018958 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
18959 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018960 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018961 if($IsNeededLib)
18962 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018963 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018964 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018965 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18966 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018967 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018968 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018969 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018970 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018971 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18972 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
18973 if($Vers)
18974 {
18975 if($LIB_EXT eq "so")
18976 { # value
18977 $Interface_Value{$LibVersion}{$Symbol} = $Value;
18978 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
18979 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018980 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018981 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18982 {
18983 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
18984 setLanguage($LibVersion, "C++");
18985 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018986 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018987 }
18988 }
18989 }
18990 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018991
18992 if($Deps and $LIB_TYPE eq "dynamic")
18993 { # dynamic library specifics
18994 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
18995 open(LIB, $Cmd." |");
18996
18997 while(<LIB>)
18998 {
18999 if(/NEEDED.+\[([^\[\]]+)\]/)
19000 { # dependencies:
19001 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19002 $NeededLib{$1} = 1;
19003 }
19004 }
19005
19006 close(LIB);
19007 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019008 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019009 if($Vers)
19010 {
19011 if(not $IsNeededLib and $LIB_EXT eq "so")
19012 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019013 my %Found = ();
19014
19015 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019016 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019017 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019018 next if(index($Symbol,"\@")==-1);
19019 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019020 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019021 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019022 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019023 if($Symbol_SameValue ne $Symbol
19024 and index($Symbol_SameValue,"\@")==-1)
19025 {
19026 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019027 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019028 last;
19029 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019030 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019031 }
19032 }
19033
19034 # default
19035 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19036 {
19037 next if(defined $Found{$Symbol});
19038 next if(index($Symbol,"\@\@")==-1);
19039
19040 if($Symbol=~/\A([^\@]*)\@\@/
19041 and not $SymVer{$LibVersion}{$1})
19042 {
19043 $SymVer{$LibVersion}{$1} = $Symbol;
19044 $Found{$Symbol} = 1;
19045 }
19046 }
19047
19048 # non-default
19049 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19050 {
19051 next if(defined $Found{$Symbol});
19052 next if(index($Symbol,"\@")==-1);
19053
19054 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19055 and not $SymVer{$LibVersion}{$1})
19056 {
19057 $SymVer{$LibVersion}{$1} = $Symbol;
19058 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019059 }
19060 }
19061 }
19062 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019063 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019064 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019065 foreach my $DyLib (sort keys(%NeededLib))
19066 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019067 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19068
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019069 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19070 {
19071 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19072 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19073 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019074 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019075 }
19076 }
19077 pop(@RecurLib);
19078 return $Library_Symbol{$LibVersion};
19079}
19080
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019081sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019082{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019083 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019084 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019085 return keys(%Prefixes);
19086}
19087
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019088sub get_prefixes_I($$)
19089{
19090 foreach my $P (@{$_[0]})
19091 {
19092 my @Parts = reverse(split(/[\/\\]+/, $P));
19093 my $Name = $Parts[0];
19094 foreach (1 .. $#Parts)
19095 {
19096 $_[1]->{$Name}{$P} = 1;
19097 last if($_>4 or $Parts[$_] eq "include");
19098 $Name = $Parts[$_].$SLASH.$Name;
19099 }
19100 }
19101}
19102
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019103sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019104{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019105 $Cache{"checkSystemFiles"} = 1;
19106
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019107 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019108
19109 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019110 {
19111 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019112
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019113 my @Files = cmd_find($DevelPath,"f");
19114 foreach my $Link (cmd_find($DevelPath,"l"))
19115 { # add symbolic links
19116 if(-f $Link) {
19117 push(@Files, $Link);
19118 }
19119 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019120
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019121 # search for headers in /usr/lib
19122 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19123 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19124 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019125
19126 # search for libraries in /usr/lib (including symbolic links)
19127 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19128 foreach my $Path (@Libs)
19129 {
19130 my $N = get_filename($Path);
19131 $SystemObjects{$N}{$Path} = 1;
19132 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019133 }
19134 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019135
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019136 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019137 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019138 next if(not -d $DevelPath);
19139 # search for all header files in the /usr/include
19140 # with or without extension (ncurses.h, QtCore, ...)
19141 push(@SysHeaders, cmd_find($DevelPath,"f"));
19142 foreach my $Link (cmd_find($DevelPath,"l"))
19143 { # add symbolic links
19144 if(-f $Link) {
19145 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019146 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019147 }
19148 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019149 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019150}
19151
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019152sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019153{
19154 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019155 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019156 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19157 {
19158 if(not -e $Dest) {
19159 exitStatus("Access_Error", "can't access \'$Dest\'");
19160 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019161 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019162 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19163 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019164 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019165 }
19166 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019167 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019168}
19169
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019170sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019171{
19172 my ($Path, $LibVersion) = @_;
19173 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019174 my $Name = get_filename($Path);
19175 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019176 return 1;
19177 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019178 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019179 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19180 return 1;
19181 }
19182 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19183 {
19184 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19185 return 1;
19186 }
19187 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019188 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019189 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019190 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019191 return 1;
19192 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019193 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019194 return 1;
19195 }
19196 }
19197 return 0;
19198}
19199
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019200sub specificHeader($$)
19201{
19202 my ($Header, $Spec) = @_;
19203 my $Name = get_filename($Header);
19204
19205 if($Spec eq "windows")
19206 {# MS Windows
19207 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19208 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19209 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19210 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19211 my @Dirs = (
19212 "win32",
19213 "win64",
19214 "win",
19215 "windows",
19216 "msvcrt"
19217 ); # /gsf-win32/
19218 if(my $DIRs = join("|", @Dirs)) {
19219 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19220 }
19221 }
19222 elsif($Spec eq "macos")
19223 { # Mac OS
19224 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19225 }
19226
19227 return 0;
19228}
19229
19230sub skipAlienHeader($)
19231{
19232 my $Path = $_[0];
19233 my $Name = get_filename($Path);
19234 my $Dir = get_dirname($Path);
19235
19236 if($Tolerance=~/2/)
19237 { # 2 - skip internal headers
19238 my @Terms = (
19239 "p",
19240 "priv",
19241 "int",
19242 "impl",
19243 "implementation",
19244 "internal",
19245 "private",
19246 "old",
19247 "compat",
19248 "debug",
19249 "test",
19250 "gen"
19251 );
19252
19253 my @Dirs = (
19254 "private",
19255 "priv",
19256 "port",
19257 "impl",
19258 "internal",
19259 "detail",
19260 "details",
19261 "old",
19262 "compat",
19263 "debug",
19264 "config",
19265 "compiler",
19266 "platform",
19267 "test"
19268 );
19269
19270 if(my $TERMs = join("|", @Terms)) {
19271 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19272 }
19273 if(my $DIRs = join("|", @Dirs)) {
19274 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19275 }
19276
19277 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19278 }
19279
19280 if($Tolerance=~/1/)
19281 { # 1 - skip non-Linux headers
19282 if($OSgroup ne "windows")
19283 {
19284 if(specificHeader($Path, "windows")) {
19285 return 1;
19286 }
19287 }
19288 if($OSgroup ne "macos")
19289 {
19290 if(specificHeader($Path, "macos")) {
19291 return 1;
19292 }
19293 }
19294 }
19295
19296 # valid
19297 return 0;
19298}
19299
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019300sub skipHeader($$)
19301{
19302 my ($Path, $LibVersion) = @_;
19303 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019304 if(defined $Cache{"skipHeader"}{$Path}) {
19305 return $Cache{"skipHeader"}{$Path};
19306 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019307 if(defined $Tolerance and $Tolerance=~/1|2/)
19308 { # --tolerant
19309 if(skipAlienHeader($Path)) {
19310 return ($Cache{"skipHeader"}{$Path} = 1);
19311 }
19312 }
19313 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19314 return 0;
19315 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019316 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19317}
19318
19319sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019320{ # returns:
19321 # 1 - if header should NOT be included and checked
19322 # 2 - if header should NOT be included, but should be checked
19323 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019324 my $Name = get_filename($Path);
19325 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019326 return $Kind;
19327 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019328 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19329 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019330 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019331 if(index($Path, $D)!=-1)
19332 {
19333 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19334 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19335 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019336 }
19337 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019338 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19339 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019340 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019341 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19342 {
19343 if($Name=~/$P/) {
19344 return $Kind;
19345 }
19346 if($P=~/[\/\\]/ and $Path=~/$P/) {
19347 return $Kind;
19348 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019349 }
19350 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019351
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019352 return 0;
19353}
19354
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019355sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019356{
19357 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019358 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019359 { # system directory
19360 return;
19361 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019362 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019363 { # already registered
19364 return;
19365 }
19366 foreach my $Path (find_libs($Dir,"",1))
19367 {
19368 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019369 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019370 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019371 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019372 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19373}
19374
19375sub registerObject($$)
19376{
19377 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019378
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019379 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019380 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019381 if($OStarget=~/linux|bsd/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019382 {
19383 if(my $SONAME = getSONAME($Path)) {
19384 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19385 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019386 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019387 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19388 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019389 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019390
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019391 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019392 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019393 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019394 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019395 if($ObjArch ne getArch_GCC($LibVersion))
19396 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19397 $CheckedArch{$LibVersion} = 1;
19398 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 +040019399 }
19400 }
19401 }
19402}
19403
19404sub getArch_Object($)
19405{
19406 my $Path = $_[0];
19407
19408 my %MachineType = (
19409 "14C" => "x86",
19410 "8664" => "x86_64",
19411 "1C0" => "arm",
19412 "200" => "ia64"
19413 );
19414
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019415 my %ArchName = (
19416 "s390:31-bit" => "s390",
19417 "s390:64-bit" => "s390x",
19418 "powerpc:common" => "ppc32",
19419 "powerpc:common64" => "ppc64",
19420 "i386:x86-64" => "x86_64",
19421 "mips:3000" => "mips",
19422 "sparc:v8plus" => "sparcv9"
19423 );
19424
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019425 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019426 {
19427 my $DumpbinCmd = get_CmdPath("dumpbin");
19428 if(not $DumpbinCmd) {
19429 exitStatus("Not_Found", "can't find \"dumpbin\"");
19430 }
19431
19432 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19433 my $Out = `$Cmd`;
19434
19435 if($Out=~/(\w+)\smachine/)
19436 {
19437 if(my $Type = $MachineType{uc($1)})
19438 {
19439 return $Type;
19440 }
19441 }
19442 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019443 elsif($OStarget=~/linux|bsd/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019444 {
19445 my $ObjdumpCmd = get_CmdPath("objdump");
19446 if(not $ObjdumpCmd) {
19447 exitStatus("Not_Found", "can't find \"objdump\"");
19448 }
19449
19450 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019451
19452 if($OSgroup eq "windows") {
19453 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19454 }
19455 else {
19456 $Cmd = "LANG=$LOCALE ".$Cmd;
19457 }
19458 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019459
19460 if($Out=~/architecture:\s+([\w\-\:]+)/)
19461 {
19462 my $Arch = $1;
19463 if($Arch=~s/\:(.+)//)
19464 {
19465 my $Suffix = $1;
19466
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019467 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019468 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019469 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019470 }
19471 }
19472
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019473 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019474 $Arch = "x86";
19475 }
19476
19477 if($Arch eq "x86-64") {
19478 $Arch = "x86_64";
19479 }
19480
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019481 if($Arch eq "ia64-elf64") {
19482 $Arch = "ia64";
19483 }
19484
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019485 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019486 }
19487 }
19488 else
19489 { # macos, etc.
19490 # TODO
19491 }
19492
19493 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019494}
19495
19496sub getSONAME($)
19497{
19498 my $Path = $_[0];
19499 return if(not $Path);
19500 if(defined $Cache{"getSONAME"}{$Path}) {
19501 return $Cache{"getSONAME"}{$Path};
19502 }
19503 my $ObjdumpCmd = get_CmdPath("objdump");
19504 if(not $ObjdumpCmd) {
19505 exitStatus("Not_Found", "can't find \"objdump\"");
19506 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019507 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019508 if($OSgroup eq "windows") {
19509 $SonameCmd .= " | find \"SONAME\"";
19510 }
19511 else {
19512 $SonameCmd .= " | grep SONAME";
19513 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019514 if(my $SonameInfo = `$SonameCmd`)
19515 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019516 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19517 return ($Cache{"getSONAME"}{$Path} = $1);
19518 }
19519 }
19520 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019521}
19522
19523sub getSOPaths_Dest($$)
19524{
19525 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019526 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019527 return ();
19528 }
19529 if(-f $Dest)
19530 {
19531 if(not parse_libname($Dest, "name", $OStarget)) {
19532 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19533 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019534 registerObject($Dest, $LibVersion);
19535 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019536 return ($Dest);
19537 }
19538 elsif(-d $Dest)
19539 {
19540 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019541 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019542 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019543 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19544 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019545 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019546 { # all files and symlinks that match the name of a library
19547 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19548 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019549 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019550 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019551 }
19552 }
19553 }
19554 else
19555 { # search for all files and symlinks
19556 foreach my $Path (find_libs($Dest,"",""))
19557 {
19558 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019559 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019560 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019561 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019562 }
19563 if($OSgroup eq "macos")
19564 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019565 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019566 {
19567 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019568 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019569 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019570 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19571 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019572 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019573 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019574 }
19575 }
19576 }
19577 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019578 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019579 }
19580 else {
19581 return ();
19582 }
19583}
19584
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019585sub isCyclical($$)
19586{
19587 my ($Stack, $Value) = @_;
19588 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019589}
19590
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019591sub getGCC_Opts($)
19592{ # to use in module
19593 my $LibVersion = $_[0];
19594
19595 my @Opts = ();
19596
19597 if($CompilerOptions{$LibVersion})
19598 { # user-defined options
19599 push(@Opts, $CompilerOptions{$LibVersion});
19600 }
19601 if($GccOptions)
19602 { # additional
19603 push(@Opts, $GccOptions);
19604 }
19605
19606 if(@Opts) {
19607 return join(" ", @Opts);
19608 }
19609
19610 return undef;
19611}
19612
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019613sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019614{
19615 my $LibVersion = $_[0];
19616
19617 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19618 return $Cache{"getArch_GCC"}{$LibVersion};
19619 }
19620
19621 my $Arch = undef;
19622
19623 if($GCC_PATH)
19624 {
19625 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19626
19627 my $Cmd = $GCC_PATH." test.c -o test";
19628 if(my $Opts = getGCC_Opts($LibVersion))
19629 { # user-defined options
19630 $Cmd .= " ".$Opts;
19631 }
19632
19633 chdir($TMP_DIR);
19634 system($Cmd);
19635 chdir($ORIG_DIR);
19636
19637 $Arch = getArch_Object("$TMP_DIR/test");
19638
19639 unlink("$TMP_DIR/test.c");
19640 unlink("$TMP_DIR/test");
19641 }
19642
19643 if(not $Arch) {
19644 exitStatus("Error", "can't check ARCH type");
19645 }
19646
19647 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19648}
19649
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019650sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019651{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019652 my $LibVersion = $_[0];
19653
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019654 my $Size = undef;
19655
19656 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019657 if(my $Arch = getArch($LibVersion))
19658 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019659 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019660 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019661 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019662 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19663 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019664 }
19665 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019666
19667 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019668 {
19669 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019670
19671 my $Cmd = $GCC_PATH." -E -dD empty.h";
19672 if(my $Opts = getGCC_Opts($LibVersion))
19673 { # user-defined options
19674 $Cmd .= " ".$Opts;
19675 }
19676
19677 chdir($TMP_DIR);
19678 my $Defines = `$Cmd`;
19679 chdir($ORIG_DIR);
19680
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019681 unlink("$TMP_DIR/empty.h");
19682
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019683 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19684 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019685 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019686 }
19687 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19688 { # GCC 3
19689 my $PTRDIFF = $1;
19690 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019691 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019692 }
19693 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019694 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019695 }
19696 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019697 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019698
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019699 if(not $Size) {
19700 exitStatus("Error", "can't check WORD size");
19701 }
19702
19703 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019704}
19705
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019706sub getWordSize($)
19707{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019708 return $WORD_SIZE{$_[0]};
19709}
19710
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019711sub majorVersion($)
19712{
19713 my $V = $_[0];
19714 return 0 if(not $V);
19715 my @VParts = split(/\./, $V);
19716 return $VParts[0];
19717}
19718
19719sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019720{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019721 my ($V1, $V2) = @_;
19722 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019723 my @V1Parts = split(/\./, $V1);
19724 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019725 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19726 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019727 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19728 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19729 }
19730 return -1 if($#V1Parts < $#V2Parts);
19731 return 1 if($#V1Parts > $#V2Parts);
19732 return 0;
19733}
19734
19735sub read_ABI_Dump($$)
19736{
19737 my ($LibVersion, $Path) = @_;
19738 return if(not $LibVersion or not -e $Path);
19739 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019740 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019741 { # input *.abi
19742 $FilePath = $Path;
19743 }
19744 else
19745 { # input *.abi.tar.gz
19746 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019747 if(not isDump_U($FilePath)) {
19748 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19749 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019750 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019751
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019752 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019753
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019754 my $Line = readLineNum($FilePath, 0);
19755 if($Line=~/xml/)
19756 { # XML format
19757 loadModule("XmlDump");
19758 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019759 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019760 else
19761 { # Perl Data::Dumper format (default)
19762 open(DUMP, $FilePath);
19763 local $/ = undef;
19764 my $Content = <DUMP>;
19765 close(DUMP);
19766
19767 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19768 { # remove temp file
19769 unlink($FilePath);
19770 }
19771 if($Content!~/};\s*\Z/) {
19772 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19773 }
19774 $ABI = eval($Content);
19775 if(not $ABI) {
19776 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019778 }
19779 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019780 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019781 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019782 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019783 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019784 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019785 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019786 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030019787 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019788
19789 if($ABI->{"ABI_DUMP_VERSION"})
19790 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019791 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019792 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019793 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019794 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019795 }
19796 else
19797 { # support for old ABI dumps
19798 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019799 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019800 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019801 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019802 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019803
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019804 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019805 {
19806 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 +040019807 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019808
19809 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19810 { # DWARF ABI Dump
19811 $UseConv_Real{$LibVersion}{"P"} = 1;
19812 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19813
19814 $UsedDump{$LibVersion}{"DWARF"} = 1;
19815
19816 $TargetComponent = "module";
19817 }
19818
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019819 if(not checkDump($LibVersion, "2.11"))
19820 { # old ABI dumps
19821 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019822 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019823 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019824 { # ABI dump created with --binary option
19825 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19826 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019827 else
19828 { # default
19829 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19830 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019831
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019832 if(defined $ABI->{"Mode"}
19833 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019834 { # --ext option
19835 $ExtendedCheck = 1;
19836 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019837 if($ABI->{"Extra"}) {
19838 $ExtraDump = 1;
19839 }
19840
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019841 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019842 {
19843 $UsedDump{$LibVersion}{"L"} = $Lang;
19844 setLanguage($LibVersion, $Lang);
19845 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019846 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019847 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019848 }
19849 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019850 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019851 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019852 if(not $TInfo)
19853 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019854 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019855 }
19856 my %Tid_TDid = ();
19857 foreach my $TDid (keys(%{$TInfo}))
19858 {
19859 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19860 {
19861 $MAX_ID = $Tid if($Tid>$MAX_ID);
19862 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019863 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019864 }
19865 }
19866 my %NewID = ();
19867 foreach my $Tid (keys(%Tid_TDid))
19868 {
19869 my @TDids = keys(%{$Tid_TDid{$Tid}});
19870 if($#TDids>=1)
19871 {
19872 foreach my $TDid (@TDids)
19873 {
19874 if($TDid) {
19875 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19876 }
19877 else
19878 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019879 my $ID = ++$MAX_ID;
19880
19881 $NewID{$TDid}{$Tid} = $ID;
19882 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19883 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019884 }
19885 }
19886 }
19887 else
19888 {
19889 my $TDid = $TDids[0];
19890 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19891 }
19892 }
19893 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
19894 {
19895 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
19896 if(defined $Info{"BaseType"})
19897 {
19898 my $Bid = $Info{"BaseType"}{"Tid"};
19899 my $BDid = $Info{"BaseType"}{"TDid"};
19900 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019901 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019902 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
19903 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
19904 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019905 }
19906 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
19907 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019908 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019909 read_Machine_DumpInfo($ABI, $LibVersion);
19910 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019911 if(not $SymbolInfo{$LibVersion})
19912 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019913 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019914 }
19915 if(not keys(%{$SymbolInfo{$LibVersion}}))
19916 { # validation of old-version dumps
19917 if(not $ExtendedCheck) {
19918 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
19919 }
19920 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019921 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019922 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019923 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019924 else
19925 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019926 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019927 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019928 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019929 }
19930 if(not $DepSymbols)
19931 { # Cannot reconstruct DepSymbols. This may result in false
19932 # positives if the old dump is for library 2. Not a problem if
19933 # old dumps are only from old libraries.
19934 $DepSymbols = {};
19935 }
19936 foreach my $Symbol (keys(%{$DepSymbols})) {
19937 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
19938 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019939 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019940 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040019941
19942 if(my $V = $TargetVersion{$LibVersion}) {
19943 $Descriptor{$LibVersion}{"Version"} = $V;
19944 }
19945 else {
19946 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
19947 }
19948
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019949 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019950 if(not $SkipTypes{$LibVersion})
19951 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019952 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019953 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030019954
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019955 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030019956 { # if not defined by -skip-symbols option
19957 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
19958 if(not $SkipSymbols{$LibVersion})
19959 { # support for old dumps
19960 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
19961 }
19962 if(not $SkipSymbols{$LibVersion})
19963 { # support for old dumps
19964 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
19965 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019966 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019967 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030019968
19969 if(not $TargetHeaders{$LibVersion})
19970 { # if not defined by -headers-list option
19971 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
19972 }
19973
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019974 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019975 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019976 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019977 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019978 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019979 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019980 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019981 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019982 if(not checkDump($LibVersion, "2.10.1")
19983 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019984 { # support for old ABI dumps: added target headers
19985 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040019986 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019987 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019988 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040019989 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019990 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019991 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019992 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019993 if(defined $ABI->{"GccConstants"})
19994 { # 3.0
19995 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
19996 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
19997 }
19998 }
19999
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020000 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020001 if(not $NestedNameSpaces{$LibVersion})
20002 { # support for old dumps
20003 # Cannot reconstruct NameSpaces. This may affect design
20004 # of the compatibility report.
20005 $NestedNameSpaces{$LibVersion} = {};
20006 }
20007 # target system type
20008 # needed to adopt HTML report
20009 if(not $DumpSystem)
20010 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020011 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020012 }
20013 # recreate environment
20014 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20015 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020016 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020017 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020018 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20019 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020020 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020021 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020022 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020023 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20024 {
20025 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20026 setLanguage($LibVersion, "C++");
20027 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020028 }
20029 }
20030 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020031 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20032 {
20033 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20034 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20035 }
20036 }
20037
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020038 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020039 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020040 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020041 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020042 {
20043 if(not $Symbol_Library{$LibVersion}{$MnglName}
20044 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20045 push(@VFunc, $MnglName);
20046 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020047 }
20048 }
20049 translateSymbols(@VFunc, $LibVersion);
20050 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020051 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20052
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020053 if(not checkDump($LibVersion, "3.0"))
20054 { # support for old ABI dumps
20055 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20056 {
20057 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20058 {
20059 if(ref($BaseType) eq "HASH") {
20060 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20061 }
20062 }
20063 }
20064 }
20065
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020066 if(not checkDump($LibVersion, "3.2"))
20067 { # support for old ABI dumps
20068 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20069 {
20070 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20071 {
20072 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20073 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20074 }
20075 }
20076 }
20077
20078 # repair target headers list
20079 delete($TargetHeaders{$LibVersion});
20080 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020081 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20082 }
20083 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20084 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020085 }
20086
20087 # non-target constants from anon enums
20088 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20089 {
20090 if(not $ExtraDump
20091 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20092 {
20093 delete($Constants{$LibVersion}{$Name});
20094 }
20095 }
20096 }
20097
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020098 if(not checkDump($LibVersion, "2.20"))
20099 { # support for old ABI dumps
20100 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20101 {
20102 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20103
20104 if($TType=~/Struct|Union|Enum|Typedef/)
20105 { # repair complex types first
20106 next;
20107 }
20108
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020109 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020110 {
20111 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20112 if($BType=~/Struct|Union|Enum/i)
20113 {
20114 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20115 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20116 }
20117 }
20118 }
20119 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20120 {
20121 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20122 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20123 if($TType=~/Struct|Union|Enum/) {
20124 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20125 }
20126 }
20127 }
20128
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020129 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020130 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020131 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20132 { # support for old ABI dumps < 2.0 (ACC 1.22)
20133 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20134 {
20135 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20136 {
20137 if($Access ne "public") {
20138 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20139 }
20140 }
20141 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20142 }
20143 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20144 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020145 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20146 { # support for old ABI dumps
20147 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20148 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020149 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20150 { # DWARF ABI Dumps
20151 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20152 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020153 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20154 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20155 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020156 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20157 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020158 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020159 foreach (keys(%{$TInfo{"Base"}})) {
20160 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020161 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020162 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020163 if($TInfo{"Type"} eq "MethodPtr")
20164 {
20165 if(defined $TInfo{"Param"})
20166 { # support for old ABI dumps <= 1.17
20167 if(not defined $TInfo{"Param"}{"0"})
20168 {
20169 my $Max = keys(%{$TInfo{"Param"}});
20170 foreach my $Pos (1 .. $Max) {
20171 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20172 }
20173 delete($TInfo{"Param"}{$Max});
20174 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20175 }
20176 }
20177 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020178 if($TInfo{"BaseType"} eq $TypeId)
20179 { # fix ABI dump
20180 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20181 }
20182 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020183 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020184 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020185 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020186 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20187 if(not $BName)
20188 { # broken type
20189 next;
20190 }
20191 if($TInfo{"Name"} eq $BName)
20192 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020193 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020194 next;
20195 }
20196 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20197 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020198 }
20199 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020200 }
20201 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20202 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020203 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020204 }
20205 }
20206
20207 if(not checkDump($LibVersion, "2.15"))
20208 { # support for old ABI dumps
20209 my %Dups = ();
20210 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20211 {
20212 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020213 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020214 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20215 { # remove template decls
20216 delete($SymbolInfo{$LibVersion}{$InfoId});
20217 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020218 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020219 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020220 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20221 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020222 { # templates
20223 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020224 }
20225 }
20226 }
20227
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020228 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20229 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020230 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20231 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20232 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20233 { # support for old ABI dumps (< 3.1)
20234 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20235 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20236 { # add "this" first parameter
20237 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20238 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20239
20240 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20241 {
20242 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20243 foreach my $Pos (reverse(0 .. $#Pos)) {
20244 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20245 }
20246 }
20247 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20248 }
20249 }
20250
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020251 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20252 { # ABI dumps have no mangled names for C-functions
20253 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20254 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020255 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20256 { # support for old ABI dumps
20257 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20258 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020259 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20260 { # DWARF ABI Dumps
20261 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20262 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020263 }
20264
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020265 $Descriptor{$LibVersion}{"Dump"} = 1;
20266}
20267
20268sub read_Machine_DumpInfo($$)
20269{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020270 my ($ABI, $LibVersion) = @_;
20271 if($ABI->{"Arch"}) {
20272 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020273 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020274 if($ABI->{"WordSize"}) {
20275 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020276 }
20277 else
20278 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020279 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020280 }
20281 if(not $WORD_SIZE{$LibVersion})
20282 { # support for old dumps (<1.23)
20283 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20284 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020285 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020286 }
20287 else
20288 {
20289 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020290 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020291 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020292 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20293 { # any "pointer"-type
20294 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020295 last;
20296 }
20297 }
20298 if($PSize)
20299 { # a pointer type size
20300 $WORD_SIZE{$LibVersion} = $PSize;
20301 }
20302 else {
20303 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20304 }
20305 }
20306 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020307 if($ABI->{"GccVersion"}) {
20308 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020309 }
20310}
20311
20312sub read_Libs_DumpInfo($$)
20313{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020314 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020315 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20316 if(not $Library_Symbol{$LibVersion})
20317 { # support for old dumps
20318 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20319 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020320 if(keys(%{$Library_Symbol{$LibVersion}})
20321 and not $DumpAPI) {
20322 $Descriptor{$LibVersion}{"Libs"} = "OK";
20323 }
20324}
20325
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020326sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020327{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020328 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020329
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020330 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020331 and not $DumpAPI) {
20332 $Descriptor{$LibVersion}{"Headers"} = "OK";
20333 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020334 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020335 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020336 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020337 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020338 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020339
20340 if(keys(%{$ABI->{"Sources"}})
20341 and not $DumpAPI) {
20342 $Descriptor{$LibVersion}{"Sources"} = "OK";
20343 }
20344 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020345 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020346 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20347 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20348 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020349}
20350
20351sub find_libs($$$)
20352{
20353 my ($Path, $Type, $MaxDepth) = @_;
20354 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020355 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020356}
20357
20358sub createDescriptor($$)
20359{
20360 my ($LibVersion, $Path) = @_;
20361 if(not $LibVersion or not $Path
20362 or not -e $Path) {
20363 return "";
20364 }
20365 if(-d $Path)
20366 { # directory with headers files and shared objects
20367 return "
20368 <version>
20369 ".$TargetVersion{$LibVersion}."
20370 </version>
20371
20372 <headers>
20373 $Path
20374 </headers>
20375
20376 <libs>
20377 $Path
20378 </libs>";
20379 }
20380 else
20381 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020382 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020383 { # standard XML-descriptor
20384 return readFile($Path);
20385 }
20386 elsif(is_header($Path, 2, $LibVersion))
20387 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020388 $CheckHeadersOnly = 1;
20389
20390 if($LibVersion==1) {
20391 $TargetVersion{$LibVersion} = "X";
20392 }
20393
20394 if($LibVersion==2) {
20395 $TargetVersion{$LibVersion} = "Y";
20396 }
20397
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020398 return "
20399 <version>
20400 ".$TargetVersion{$LibVersion}."
20401 </version>
20402
20403 <headers>
20404 $Path
20405 </headers>
20406
20407 <libs>
20408 none
20409 </libs>";
20410 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020411 else
20412 { # standard XML-descriptor
20413 return readFile($Path);
20414 }
20415 }
20416}
20417
20418sub detect_lib_default_paths()
20419{
20420 my %LPaths = ();
20421 if($OSgroup eq "bsd")
20422 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020423 if(my $LdConfig = get_CmdPath("ldconfig"))
20424 {
20425 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20426 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020427 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20428 {
20429 my $Name = "lib".$1;
20430 if(not defined $LPaths{$Name}) {
20431 $LPaths{$Name} = $2;
20432 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020433 }
20434 }
20435 }
20436 else {
20437 printMsg("WARNING", "can't find ldconfig");
20438 }
20439 }
20440 else
20441 {
20442 if(my $LdConfig = get_CmdPath("ldconfig"))
20443 {
20444 if($SystemRoot and $OSgroup eq "linux")
20445 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20446 if(-e $SystemRoot."/etc/ld.so.conf") {
20447 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20448 }
20449 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020450 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20451 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020452 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20453 {
20454 my ($Name, $Path) = ($1, $2);
20455 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020456 if(not defined $LPaths{$Name})
20457 { # get first element from the list of available paths
20458
20459 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20460 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20461 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20462
20463 $LPaths{$Name} = $Path;
20464 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020465 }
20466 }
20467 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020468 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020469 printMsg("WARNING", "can't find ldconfig");
20470 }
20471 }
20472 return \%LPaths;
20473}
20474
20475sub detect_bin_default_paths()
20476{
20477 my $EnvPaths = $ENV{"PATH"};
20478 if($OSgroup eq "beos") {
20479 $EnvPaths.=":".$ENV{"BETOOLS"};
20480 }
20481 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020482 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020483 {
20484 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020485 next if(not $Path);
20486 if($SystemRoot
20487 and $Path=~/\A\Q$SystemRoot\E\//)
20488 { # do NOT use binaries from target system
20489 next;
20490 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020491 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020492 }
20493}
20494
20495sub detect_inc_default_paths()
20496{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020497 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020498 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020499 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020500 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020501 next if(index($Line, "/cc1plus ")!=-1);
20502
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020503 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20504 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020505 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020506 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020507 if(index($Path, "c++")!=-1
20508 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020509 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020510 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020511 if(not defined $MAIN_CPP_DIR
20512 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20513 $MAIN_CPP_DIR = $Path;
20514 }
20515 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020516 elsif(index($Path, "gcc")!=-1) {
20517 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020518 }
20519 else
20520 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020521 if($Path=~/local[\/\\]+include/)
20522 { # local paths
20523 next;
20524 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020525 if($SystemRoot
20526 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20527 { # The GCC include path for user headers is not a part of the system root
20528 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20529 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20530 next;
20531 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020532 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020533 }
20534 }
20535 }
20536 unlink("$TMP_DIR/empty.h");
20537 return %DPaths;
20538}
20539
20540sub detect_default_paths($)
20541{
20542 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20543 my $Search = $_[0];
20544 if($Search!~/inc/) {
20545 $HSearch = 0;
20546 }
20547 if($Search!~/lib/) {
20548 $LSearch = 0;
20549 }
20550 if($Search!~/bin/) {
20551 $BSearch = 0;
20552 }
20553 if($Search!~/gcc/) {
20554 $GSearch = 0;
20555 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020556 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020557 { # <search_headers> section of the XML descriptor
20558 # do NOT search for systems headers
20559 $HSearch = 0;
20560 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020561 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020562 { # <search_libs> section of the XML descriptor
20563 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020564 $LSearch = 0;
20565 }
20566 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20567 { # additional search paths
20568 next if($Type eq "include" and not $HSearch);
20569 next if($Type eq "lib" and not $LSearch);
20570 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020571 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020572 }
20573 if($OSgroup ne "windows")
20574 { # unix-like
20575 foreach my $Type ("include", "lib", "bin")
20576 { # automatic detection of system "devel" directories
20577 next if($Type eq "include" and not $HSearch);
20578 next if($Type eq "lib" and not $LSearch);
20579 next if($Type eq "bin" and not $BSearch);
20580 my ($UsrDir, $RootDir) = ("/usr", "/");
20581 if($SystemRoot and $Type ne "bin")
20582 { # 1. search for target headers and libraries
20583 # 2. use host commands: ldconfig, readelf, etc.
20584 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20585 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020586 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020587 if(-d $RootDir."/".$Type)
20588 { # if "/lib" is symbolic link
20589 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020590 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020591 }
20592 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020593 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020594 }
20595 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020596 if(-d $UsrDir)
20597 {
20598 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020599 if(-d $UsrDir."/".$Type)
20600 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020601 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020602 }
20603 }
20604 }
20605 }
20606 if($BSearch)
20607 {
20608 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020609 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020610 }
20611 # check environment variables
20612 if($OSgroup eq "beos")
20613 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020614 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020615 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020616 if($_ eq ".") {
20617 next;
20618 }
20619 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20620 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20621 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020622 }
20623 }
20624 if($HSearch)
20625 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020626 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20627 split(/:|;/, $ENV{"BEINCLUDES"})
20628 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020629 }
20630 if($LSearch)
20631 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020632 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20633 split(/:|;/, $ENV{"BELIBRARIES"}),
20634 split(/:|;/, $ENV{"LIBRARY_PATH"})
20635 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020636 }
20637 }
20638 if($LSearch)
20639 { # using linker to get system paths
20640 if(my $LPaths = detect_lib_default_paths())
20641 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020642 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020643 foreach my $Name (keys(%{$LPaths}))
20644 {
20645 if($SystemRoot
20646 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20647 { # wrong ldconfig configuration
20648 # check your <sysroot>/etc/ld.so.conf
20649 next;
20650 }
20651 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020652 if(my $Dir = get_dirname($LPaths->{$Name})) {
20653 $Dirs{$Dir} = 1;
20654 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020655 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020656 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020657 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020658 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020659 }
20660 if($BSearch)
20661 {
20662 if($CrossGcc)
20663 { # --cross-gcc=arm-linux-gcc
20664 if(-e $CrossGcc)
20665 { # absolute or relative path
20666 $GCC_PATH = get_abs_path($CrossGcc);
20667 }
20668 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20669 { # command name
20670 $GCC_PATH = $CrossGcc;
20671 }
20672 else {
20673 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20674 }
20675 if($GCC_PATH=~/\s/) {
20676 $GCC_PATH = "\"".$GCC_PATH."\"";
20677 }
20678 }
20679 }
20680 if($GSearch)
20681 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020682 if(not $CrossGcc)
20683 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020684 $GCC_PATH = get_CmdPath("gcc");
20685 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020686 if(not $GCC_PATH)
20687 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020688 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020689 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020690 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020691 { # select the latest version
20692 @GCCs = sort {$b cmp $a} @GCCs;
20693 if(check_gcc($GCCs[0], "3"))
20694 {
20695 $GCC_PATH = $GCCs[0];
20696 last;
20697 }
20698 }
20699 }
20700 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020701 if(not $GCC_PATH) {
20702 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20703 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020704
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020705 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020706 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020707 my $GccTarget = get_dumpmachine($GCC_PATH);
20708
20709 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020710 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020711 $OStarget = "linux";
20712 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020713 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020714 elsif($GccTarget=~/symbian/)
20715 {
20716 $OStarget = "symbian";
20717 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20718 }
20719
20720 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
20721
20722 # check GCC version
20723 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
20724 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
20725 # introduced in 4.8
20726 # fixed in 4.8.3
20727 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20728 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020729 }
20730 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020731 else {
20732 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020733 }
20734 }
20735 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020736 {
20737 # GCC standard paths
20738 if($GCC_PATH and not $NoStdInc)
20739 {
20740 my %DPaths = detect_inc_default_paths();
20741 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20742 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20743 @DefaultIncPaths = @{$DPaths{"Inc"}};
20744 push_U($SystemPaths{"include"}, @DefaultIncPaths);
20745 }
20746
20747 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020748 my $IncPath = "/usr/include";
20749 if($SystemRoot) {
20750 $IncPath = $SystemRoot.$IncPath;
20751 }
20752 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020753 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020754 }
20755 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020756
20757 if($ExtraInfo)
20758 {
20759 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20760 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20761 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020762}
20763
20764sub getLIB_EXT($)
20765{
20766 my $Target = $_[0];
20767 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20768 return $Ext;
20769 }
20770 return $OS_LibExt{$LIB_TYPE}{"default"};
20771}
20772
20773sub getAR_EXT($)
20774{
20775 my $Target = $_[0];
20776 if(my $Ext = $OS_Archive{$Target}) {
20777 return $Ext;
20778 }
20779 return $OS_Archive{"default"};
20780}
20781
20782sub get_dumpversion($)
20783{
20784 my $Cmd = $_[0];
20785 return "" if(not $Cmd);
20786 if($Cache{"get_dumpversion"}{$Cmd}) {
20787 return $Cache{"get_dumpversion"}{$Cmd};
20788 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020789 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020790 chomp($V);
20791 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20792}
20793
20794sub get_dumpmachine($)
20795{
20796 my $Cmd = $_[0];
20797 return "" if(not $Cmd);
20798 if($Cache{"get_dumpmachine"}{$Cmd}) {
20799 return $Cache{"get_dumpmachine"}{$Cmd};
20800 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020801 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020802 chomp($Machine);
20803 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20804}
20805
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020806sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020807{
20808 my $Cmd = $_[0];
20809 return "" if(not $Cmd);
20810 my @Options = (
20811 "--version",
20812 "-help"
20813 );
20814 foreach my $Opt (@Options)
20815 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020816 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020817 if($Info) {
20818 return 1;
20819 }
20820 }
20821 return 0;
20822}
20823
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020824sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020825{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020826 my ($Cmd, $ReqVer) = @_;
20827 return 0 if(not $Cmd or not $ReqVer);
20828 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20829 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020830 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020831 if(my $GccVer = get_dumpversion($Cmd))
20832 {
20833 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20834 if(cmpVersions($GccVer, $ReqVer)>=0) {
20835 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20836 }
20837 }
20838 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020839}
20840
20841sub get_depth($)
20842{
20843 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020844 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020845 }
20846 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20847}
20848
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020849sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020850{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020851 return if($Cache{"registerGccHeaders"}); # this function should be called once
20852
20853 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020854 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020855 my @Headers = cmd_find($Path,"f");
20856 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20857 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020858 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020859 my $FileName = get_filename($HPath);
20860 if(not defined $DefaultGccHeader{$FileName})
20861 { # skip duplicated
20862 $DefaultGccHeader{$FileName} = $HPath;
20863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020864 }
20865 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020866 $Cache{"registerGccHeaders"} = 1;
20867}
20868
20869sub registerCppHeaders()
20870{
20871 return if($Cache{"registerCppHeaders"}); # this function should be called once
20872
20873 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020874 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020875 my @Headers = cmd_find($CppDir,"f");
20876 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20877 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020878 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020879 my $FileName = get_filename($Path);
20880 if(not defined $DefaultCppHeader{$FileName})
20881 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020882 $DefaultCppHeader{$FileName} = $Path;
20883 }
20884 }
20885 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020886 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020887}
20888
20889sub parse_libname($$$)
20890{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020891 return "" if(not $_[0]);
20892 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20893 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020894 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020895 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20896}
20897
20898sub parse_libname_I($$$)
20899{
20900 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020901
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020902 if($Target eq "symbian") {
20903 return parse_libname_symbian($Name, $Type);
20904 }
20905 elsif($Target eq "windows") {
20906 return parse_libname_windows($Name, $Type);
20907 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020908
20909 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020910 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020911 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020912 { # libSDL-1.2.so.0.7.1
20913 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020914 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020915 if($Type eq "name")
20916 { # libSDL-1.2
20917 # libwbxml2
20918 return $2;
20919 }
20920 elsif($Type eq "name+ext")
20921 { # libSDL-1.2.so
20922 # libwbxml2.so
20923 return $1;
20924 }
20925 elsif($Type eq "version")
20926 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020927 if(defined $7
20928 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020929 { # 0.7.1
20930 return $7;
20931 }
20932 else
20933 { # libc-2.5.so (=>2.5 version)
20934 my $MV = $5;
20935 $MV=~s/\A[\-\_]+//g;
20936 return $MV;
20937 }
20938 }
20939 elsif($Type eq "short")
20940 { # libSDL
20941 # libwbxml2
20942 return $3;
20943 }
20944 elsif($Type eq "shortest")
20945 { # SDL
20946 # wbxml
20947 return shortest_name($3);
20948 }
20949 }
20950 return "";# error
20951}
20952
20953sub parse_libname_symbian($$)
20954{
20955 my ($Name, $Type) = @_;
20956 my $Ext = getLIB_EXT("symbian");
20957 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
20958 { # libpthread{00010001}.dso
20959 if($Type eq "name")
20960 { # libpthread{00010001}
20961 return $2;
20962 }
20963 elsif($Type eq "name+ext")
20964 { # libpthread{00010001}.dso
20965 return $1;
20966 }
20967 elsif($Type eq "version")
20968 { # 00010001
20969 my $V = $4;
20970 $V=~s/\{(.+)\}/$1/;
20971 return $V;
20972 }
20973 elsif($Type eq "short")
20974 { # libpthread
20975 return $3;
20976 }
20977 elsif($Type eq "shortest")
20978 { # pthread
20979 return shortest_name($3);
20980 }
20981 }
20982 return "";# error
20983}
20984
20985sub parse_libname_windows($$)
20986{
20987 my ($Name, $Type) = @_;
20988 my $Ext = getLIB_EXT("windows");
20989 if($Name=~/((.+?)\.$Ext)\Z/)
20990 { # netapi32.dll
20991 if($Type eq "name")
20992 { # netapi32
20993 return $2;
20994 }
20995 elsif($Type eq "name+ext")
20996 { # netapi32.dll
20997 return $1;
20998 }
20999 elsif($Type eq "version")
21000 { # DLL version embedded
21001 # at binary-level
21002 return "";
21003 }
21004 elsif($Type eq "short")
21005 { # netapi32
21006 return $2;
21007 }
21008 elsif($Type eq "shortest")
21009 { # netapi
21010 return shortest_name($2);
21011 }
21012 }
21013 return "";# error
21014}
21015
21016sub shortest_name($)
21017{
21018 my $Name = $_[0];
21019 # remove prefix
21020 $Name=~s/\A(lib|open)//;
21021 # remove suffix
21022 $Name=~s/[\W\d_]+\Z//i;
21023 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21024 return $Name;
21025}
21026
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021027sub createSymbolsList($$$$$)
21028{
21029 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021030
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021031 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021032 prepareSymbols(1);
21033
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021034 my %SymbolHeaderLib = ();
21035 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021036
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021037 # Get List
21038 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21039 {
21040 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021041 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021042 next;
21043 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021044 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021045 { # skip other symbols
21046 next;
21047 }
21048 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21049 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021050 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021051 next;
21052 }
21053 my $DyLib = $Symbol_Library{1}{$Symbol};
21054 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021055 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021056 next;
21057 }
21058 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21059 $Total+=1;
21060 }
21061 # Draw List
21062 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21063 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21064 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21065 {
21066 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21067 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021068 my %NS_Symbol = ();
21069 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021070 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021071 }
21072 foreach my $NameSpace (sort keys(%NS_Symbol))
21073 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021074 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021075 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21076 foreach my $Symbol (@SortedInterfaces)
21077 {
21078 my $SubReport = "";
21079 my $Signature = get_Signature($Symbol, 1);
21080 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021081 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021082 }
21083 if($Symbol=~/\A(_Z|\?)/)
21084 {
21085 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021086 $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 +040021087 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021088 else {
21089 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21090 }
21091 }
21092 else
21093 {
21094 if($Signature) {
21095 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21096 }
21097 else {
21098 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21099 }
21100 }
21101 $SYMBOLS_LIST .= $SubReport;
21102 }
21103 }
21104 $SYMBOLS_LIST .= "<br/>\n";
21105 }
21106 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021107 # clear info
21108 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21109 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21110 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21111 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021112 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021113 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021114 my $CssStyles = readModule("Styles", "SymbolsList.css");
21115 my $JScripts = readModule("Scripts", "Sections.js");
21116 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021117 my $Title = "$LName: public symbols";
21118 my $Keywords = "$LName, API, symbols";
21119 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021120 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021121 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030021122 <br/><br/><hr/>\n".getReportFooter("Single")."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021123 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021124 writeFile($SaveTo, $SYMBOLS_LIST);
21125}
21126
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021127sub add_target_libs($)
21128{
21129 foreach (@{$_[0]}) {
21130 $TargetLibs{$_} = 1;
21131 }
21132}
21133
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021134sub is_target_lib($)
21135{
21136 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021137 if(not $LName) {
21138 return 0;
21139 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021140 if($TargetLibraryName
21141 and $LName!~/\Q$TargetLibraryName\E/) {
21142 return 0;
21143 }
21144 if(keys(%TargetLibs)
21145 and not $TargetLibs{$LName}
21146 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21147 return 0;
21148 }
21149 return 1;
21150}
21151
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021152sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021153{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021154 my ($H, $V) = @_;
21155 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021156 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021157 if($TargetHeaders{$V}{$H}) {
21158 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021159 }
21160 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021161 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021162}
21163
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021164sub readLibs($)
21165{
21166 my $LibVersion = $_[0];
21167 if($OStarget eq "windows")
21168 { # dumpbin.exe will crash
21169 # without VS Environment
21170 check_win32_env();
21171 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021172 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021173 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021174 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021175}
21176
21177sub dump_sorting($)
21178{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021179 my $Hash = $_[0];
21180 return [] if(not $Hash);
21181 my @Keys = keys(%{$Hash});
21182 return [] if($#Keys<0);
21183 if($Keys[0]=~/\A\d+\Z/)
21184 { # numbers
21185 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021186 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021187 else
21188 { # strings
21189 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021190 }
21191}
21192
21193sub printMsg($$)
21194{
21195 my ($Type, $Msg) = @_;
21196 if($Type!~/\AINFO/) {
21197 $Msg = $Type.": ".$Msg;
21198 }
21199 if($Type!~/_C\Z/) {
21200 $Msg .= "\n";
21201 }
21202 if($Quiet)
21203 { # --quiet option
21204 appendFile($COMMON_LOG_PATH, $Msg);
21205 }
21206 else
21207 {
21208 if($Type eq "ERROR") {
21209 print STDERR $Msg;
21210 }
21211 else {
21212 print $Msg;
21213 }
21214 }
21215}
21216
21217sub exitStatus($$)
21218{
21219 my ($Code, $Msg) = @_;
21220 printMsg("ERROR", $Msg);
21221 exit($ERROR_CODE{$Code});
21222}
21223
21224sub exitReport()
21225{ # the tool has run without any errors
21226 printReport();
21227 if($COMPILE_ERRORS)
21228 { # errors in headers may add false positives/negatives
21229 exit($ERROR_CODE{"Compile_Error"});
21230 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021231 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21232 { # --binary
21233 exit($ERROR_CODE{"Incompatible"});
21234 }
21235 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21236 { # --source
21237 exit($ERROR_CODE{"Incompatible"});
21238 }
21239 elsif($RESULT{"Source"}{"Problems"}
21240 or $RESULT{"Binary"}{"Problems"})
21241 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021242 exit($ERROR_CODE{"Incompatible"});
21243 }
21244 else {
21245 exit($ERROR_CODE{"Compatible"});
21246 }
21247}
21248
21249sub readRules($)
21250{
21251 my $Kind = $_[0];
21252 if(not -f $RULES_PATH{$Kind}) {
21253 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21254 }
21255 my $Content = readFile($RULES_PATH{$Kind});
21256 while(my $Rule = parseTag(\$Content, "rule"))
21257 {
21258 my $RId = parseTag(\$Rule, "id");
21259 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21260 foreach my $Prop (@Properties) {
21261 if(my $Value = parseTag(\$Rule, lc($Prop)))
21262 {
21263 $Value=~s/\n[ ]*//;
21264 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21265 }
21266 }
21267 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21268 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21269 }
21270 else {
21271 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21272 }
21273 }
21274}
21275
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021276sub getReportPath($)
21277{
21278 my $Level = $_[0];
21279 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21280 if($Level eq "Binary")
21281 {
21282 if($BinaryReportPath)
21283 { # --bin-report-path
21284 return $BinaryReportPath;
21285 }
21286 elsif($OutputReportPath)
21287 { # --report-path
21288 return $OutputReportPath;
21289 }
21290 else
21291 { # default
21292 return $Dir."/abi_compat_report.$ReportFormat";
21293 }
21294 }
21295 elsif($Level eq "Source")
21296 {
21297 if($SourceReportPath)
21298 { # --src-report-path
21299 return $SourceReportPath;
21300 }
21301 elsif($OutputReportPath)
21302 { # --report-path
21303 return $OutputReportPath;
21304 }
21305 else
21306 { # default
21307 return $Dir."/src_compat_report.$ReportFormat";
21308 }
21309 }
21310 else
21311 {
21312 if($OutputReportPath)
21313 { # --report-path
21314 return $OutputReportPath;
21315 }
21316 else
21317 { # default
21318 return $Dir."/compat_report.$ReportFormat";
21319 }
21320 }
21321}
21322
21323sub printStatMsg($)
21324{
21325 my $Level = $_[0];
21326 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21327}
21328
21329sub listAffected($)
21330{
21331 my $Level = $_[0];
21332 my $List = "";
21333 foreach (keys(%{$TotalAffected{$Level}}))
21334 {
21335 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21336 { # skip "Low"-severity problems
21337 next;
21338 }
21339 $List .= "$_\n";
21340 }
21341 my $Dir = get_dirname(getReportPath($Level));
21342 if($Level eq "Binary") {
21343 writeFile($Dir."/abi_affected.txt", $List);
21344 }
21345 elsif($Level eq "Source") {
21346 writeFile($Dir."/src_affected.txt", $List);
21347 }
21348}
21349
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021350sub printReport()
21351{
21352 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021353 createReport();
21354 if($JoinReport or $DoubleReport)
21355 {
21356 if($RESULT{"Binary"}{"Problems"}
21357 or $RESULT{"Source"}{"Problems"}) {
21358 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021359 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021360 else {
21361 printMsg("INFO", "result: COMPATIBLE");
21362 }
21363 printStatMsg("Binary");
21364 printStatMsg("Source");
21365 if($ListAffected)
21366 { # --list-affected
21367 listAffected("Binary");
21368 listAffected("Source");
21369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021370 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021371 elsif($BinaryOnly)
21372 {
21373 if($RESULT{"Binary"}{"Problems"}) {
21374 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21375 }
21376 else {
21377 printMsg("INFO", "result: COMPATIBLE");
21378 }
21379 printStatMsg("Binary");
21380 if($ListAffected)
21381 { # --list-affected
21382 listAffected("Binary");
21383 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021384 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021385 elsif($SourceOnly)
21386 {
21387 if($RESULT{"Source"}{"Problems"}) {
21388 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21389 }
21390 else {
21391 printMsg("INFO", "result: COMPATIBLE");
21392 }
21393 printStatMsg("Source");
21394 if($ListAffected)
21395 { # --list-affected
21396 listAffected("Source");
21397 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021398 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021399 if($StdOut)
21400 {
21401 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021402 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021403 printMsg("INFO", "compatibility report has been generated to stdout");
21404 }
21405 else
21406 { # default
21407 printMsg("INFO", "compatibility reports have been generated to stdout");
21408 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021409 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021410 else
21411 {
21412 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021413 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021414 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21415 }
21416 elsif($DoubleReport)
21417 { # default
21418 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21419 }
21420 elsif($BinaryOnly)
21421 { # --binary
21422 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21423 }
21424 elsif($SourceOnly)
21425 { # --source
21426 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21427 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021428 }
21429}
21430
21431sub check_win32_env()
21432{
21433 if(not $ENV{"DevEnvDir"}
21434 or not $ENV{"LIB"}) {
21435 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21436 }
21437}
21438
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021439sub diffSets($$)
21440{
21441 my ($S1, $S2) = @_;
21442 my @SK1 = keys(%{$S1});
21443 my @SK2 = keys(%{$S2});
21444 if($#SK1!=$#SK2) {
21445 return 1;
21446 }
21447 foreach my $K1 (@SK1)
21448 {
21449 if(not defined $S2->{$K1}) {
21450 return 1;
21451 }
21452 }
21453 return 0;
21454}
21455
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021456sub defaultDumpPath($$)
21457{
21458 my ($N, $V) = @_;
21459 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21460}
21461
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021462sub create_ABI_Dump()
21463{
21464 if(not -e $DumpAPI) {
21465 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21466 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021467
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021468 if(isDump($DumpAPI)) {
21469 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021470 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021471 else {
21472 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021473 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021474
21475 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021476 { # set to default: N
21477 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021478 }
21479
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021480 initLogging(1);
21481 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021482
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021483 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021484 if($OutputDumpPath)
21485 { # user defined path
21486 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021487 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021488 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21489
21490 if(not $Archive and not $StdOut)
21491 { # check archive utilities
21492 if($OSgroup eq "windows")
21493 { # using zip
21494 my $ZipCmd = get_CmdPath("zip");
21495 if(not $ZipCmd) {
21496 exitStatus("Not_Found", "can't find \"zip\"");
21497 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021498 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021499 else
21500 { # using tar and gzip
21501 my $TarCmd = get_CmdPath("tar");
21502 if(not $TarCmd) {
21503 exitStatus("Not_Found", "can't find \"tar\"");
21504 }
21505 my $GzipCmd = get_CmdPath("gzip");
21506 if(not $GzipCmd) {
21507 exitStatus("Not_Found", "can't find \"gzip\"");
21508 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021509 }
21510 }
21511
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021512 if(not $Descriptor{1}{"Dump"})
21513 {
21514 if(not $CheckHeadersOnly) {
21515 readLibs(1);
21516 }
21517 if($CheckHeadersOnly) {
21518 setLanguage(1, "C++");
21519 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021520 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021521 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021522 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021523 if(not $Descriptor{1}{"Dump"})
21524 {
21525 if($Descriptor{1}{"Headers"}) {
21526 readHeaders(1);
21527 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021528 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021529 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021530 if(not keys(%{$SymbolInfo{1}}))
21531 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021532 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021533 {
21534 if($CheckHeadersOnly) {
21535 exitStatus("Empty_Set", "the set of public symbols is empty");
21536 }
21537 else {
21538 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21539 }
21540 }
21541 }
21542 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021543 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021544 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21545 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021546 if($ExtraDump)
21547 { # add unmangled names to the ABI dump
21548 my @Names = ();
21549 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21550 {
21551 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21552 push(@Names, $MnglName);
21553 }
21554 }
21555 translateSymbols(@Names, 1);
21556 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21557 {
21558 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21559 {
21560 if(my $Unmangled = $tr_name{$MnglName})
21561 {
21562 if($MnglName ne $Unmangled) {
21563 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21564 }
21565 }
21566 }
21567 }
21568 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021569
21570 my %GccConstants = (); # built-in GCC constants
21571 foreach my $Name (keys(%{$Constants{1}}))
21572 {
21573 if(not defined $Constants{1}{$Name}{"Header"})
21574 {
21575 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21576 delete($Constants{1}{$Name});
21577 }
21578 }
21579
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021580 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021581 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021582 "TypeInfo" => $TypeInfo{1},
21583 "SymbolInfo" => $SymbolInfo{1},
21584 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021585 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021586 "SymbolVersion" => $SymVer{1},
21587 "LibraryVersion" => $Descriptor{1}{"Version"},
21588 "LibraryName" => $TargetLibraryName,
21589 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021590 "SkipTypes" => $SkipTypes{1},
21591 "SkipSymbols" => $SkipSymbols{1},
21592 "SkipNameSpaces" => $SkipNameSpaces{1},
21593 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021594 "Headers" => \%HeadersInfo,
21595 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021596 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021597 "NameSpaces" => $NestedNameSpaces{1},
21598 "Target" => $OStarget,
21599 "Arch" => getArch(1),
21600 "WordSize" => $WORD_SIZE{1},
21601 "GccVersion" => get_dumpversion($GCC_PATH),
21602 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21603 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21604 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021605 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021606 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021607 }
21608 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021609 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021610 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021611 if($ExtendedCheck)
21612 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021613 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021614 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021615 if($BinaryOnly)
21616 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021617 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021618 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021619 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021620 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021621 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021622 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21623 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021624 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021625
21626 my $ABI_DUMP = "";
21627 if($UseXML)
21628 {
21629 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021630 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021631 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021632 else
21633 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021634 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021635 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021636 if($StdOut)
21637 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021638 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021639 printMsg("INFO", "ABI dump has been generated to stdout");
21640 return;
21641 }
21642 else
21643 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021644 my ($DDir, $DName) = separate_path($DumpPath);
21645 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021646 if(not $Archive) {
21647 $DPath = $DumpPath;
21648 }
21649
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021650 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021651
21652 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021653 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021654 close(DUMP);
21655
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021656 if(not -s $DPath) {
21657 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21658 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021659 if($Archive) {
21660 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021661 }
21662
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021663 if($OutputDumpPath) {
21664 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021665 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021666 else {
21667 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21668 }
21669 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 +040021670 }
21671}
21672
21673sub quickEmptyReports()
21674{ # Quick "empty" reports
21675 # 4 times faster than merging equal dumps
21676 # NOTE: the dump contains the "LibraryVersion" attribute
21677 # if you change the version, then your dump will be different
21678 # OVERCOME: use -v1 and v2 options for comparing dumps
21679 # and don't change version in the XML descriptor (and dumps)
21680 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21681 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21682 {
21683 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21684 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21685 if($FilePath1 and $FilePath2)
21686 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021687 my $Line = readLineNum($FilePath1, 0);
21688 if($Line=~/xml/)
21689 { # XML format
21690 # is not supported yet
21691 return;
21692 }
21693
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021694 local $/ = undef;
21695
21696 open(DUMP1, $FilePath1);
21697 my $Content1 = <DUMP1>;
21698 close(DUMP1);
21699
21700 open(DUMP2, $FilePath2);
21701 my $Content2 = <DUMP2>;
21702 close(DUMP2);
21703
21704 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021705 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021706 # clean memory
21707 undef $Content2;
21708
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021709 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021710 my $ABIdump = eval($Content1);
21711
21712 # clean memory
21713 undef $Content1;
21714
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021715 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021716 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 +040021717 }
21718 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021719 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021720 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21721 }
21722 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021723 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021724 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21725 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021726 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021727 read_Libs_DumpInfo($ABIdump, 1);
21728 read_Machine_DumpInfo($ABIdump, 1);
21729 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021730
21731 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21732 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21733
21734 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21735 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21736
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021737 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21738 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21739 exitReport();
21740 }
21741 }
21742 }
21743}
21744
21745sub initLogging($)
21746{
21747 my $LibVersion = $_[0];
21748 # create log directory
21749 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21750 if($OutputLogPath{$LibVersion})
21751 { # user-defined by -log-path option
21752 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21753 }
21754 if($LogMode ne "n") {
21755 mkpath($LOG_DIR);
21756 }
21757 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021758 if($Debug)
21759 { # debug directory
21760 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021761
21762 if(not $ExtraInfo)
21763 { # enable --extra-info
21764 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21765 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021766 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021767 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021768}
21769
21770sub writeLog($$)
21771{
21772 my ($LibVersion, $Msg) = @_;
21773 if($LogMode ne "n") {
21774 appendFile($LOG_PATH{$LibVersion}, $Msg);
21775 }
21776}
21777
21778sub resetLogging($)
21779{
21780 my $LibVersion = $_[0];
21781 if($LogMode!~/a|n/)
21782 { # remove old log
21783 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021784 if($Debug) {
21785 rmtree($DEBUG_PATH{$LibVersion});
21786 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021787 }
21788}
21789
21790sub printErrorLog($)
21791{
21792 my $LibVersion = $_[0];
21793 if($LogMode ne "n") {
21794 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21795 }
21796}
21797
21798sub isDump($)
21799{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021800 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
21801 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021802 return $1;
21803 }
21804 return 0;
21805}
21806
21807sub isDump_U($)
21808{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021809 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021810 return $1;
21811 }
21812 return 0;
21813}
21814
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021815sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021816{
21817 # read input XML descriptors or ABI dumps
21818 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021819 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021820 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021821 if(not -e $Descriptor{1}{"Path"}) {
21822 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021823 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021824
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021825 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021826 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021827 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021828 if(not -e $Descriptor{2}{"Path"}) {
21829 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021830 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021831
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021832 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021833 if(isDump($Descriptor{1}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021834 and isDump($Descriptor{2}{"Path"}))
21835 { # optimization: equal ABI dumps
21836 quickEmptyReports();
21837 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021838
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021839 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021840
21841 if(isDump($Descriptor{1}{"Path"})) {
21842 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021843 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021844 else {
21845 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
21846 }
21847
21848 if(isDump($Descriptor{2}{"Path"})) {
21849 read_ABI_Dump(2, $Descriptor{2}{"Path"});
21850 }
21851 else {
21852 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021853 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021854
21855 if(not $Descriptor{1}{"Version"})
21856 { # set to default: X
21857 $Descriptor{1}{"Version"} = "X";
21858 }
21859
21860 if(not $Descriptor{2}{"Version"})
21861 { # set to default: Y
21862 $Descriptor{2}{"Version"} = "Y";
21863 }
21864
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021865 initLogging(1);
21866 initLogging(2);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021867
21868 # check input data
21869 if(not $Descriptor{1}{"Headers"}) {
21870 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021871 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021872 if(not $Descriptor{2}{"Headers"}) {
21873 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021874 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021875
21876 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021877 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021878 if(not $Descriptor{1}{"Libs"}) {
21879 exitStatus("Error", "can't find libraries info in descriptor d1");
21880 }
21881 if(not $Descriptor{2}{"Libs"}) {
21882 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021883 }
21884 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021885
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021886 if($UseDumps)
21887 { # --use-dumps
21888 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021889 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
21890 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021891
21892 unlink($DumpPath1);
21893 unlink($DumpPath2);
21894
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021895 my $pid = fork();
21896 if($pid)
21897 { # dump on two CPU cores
21898 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
21899 if($RelativeDirectory{1}) {
21900 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
21901 }
21902 if($OutputLogPath{1}) {
21903 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
21904 }
21905 if($CrossGcc) {
21906 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21907 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021908 if($Quiet)
21909 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021910 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021911 @PARAMS = (@PARAMS, "-logging-mode", "a");
21912 }
21913 elsif($LogMode and $LogMode ne "w")
21914 { # "w" is default
21915 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021916 }
21917 if($ExtendedCheck) {
21918 @PARAMS = (@PARAMS, "-extended");
21919 }
21920 if($UserLang) {
21921 @PARAMS = (@PARAMS, "-lang", $UserLang);
21922 }
21923 if($TargetVersion{1}) {
21924 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
21925 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021926 if($BinaryOnly) {
21927 @PARAMS = (@PARAMS, "-binary");
21928 }
21929 if($SourceOnly) {
21930 @PARAMS = (@PARAMS, "-source");
21931 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021932 if($SortDump) {
21933 @PARAMS = (@PARAMS, "-sort");
21934 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021935 if($DumpFormat and $DumpFormat ne "perl") {
21936 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
21937 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021938 if($CheckHeadersOnly) {
21939 @PARAMS = (@PARAMS, "-headers-only");
21940 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021941 if($Debug)
21942 {
21943 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021944 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021945 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021946 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021947 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021948 exit(1);
21949 }
21950 }
21951 else
21952 { # child
21953 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
21954 if($RelativeDirectory{2}) {
21955 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
21956 }
21957 if($OutputLogPath{2}) {
21958 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
21959 }
21960 if($CrossGcc) {
21961 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21962 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021963 if($Quiet)
21964 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021965 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021966 @PARAMS = (@PARAMS, "-logging-mode", "a");
21967 }
21968 elsif($LogMode and $LogMode ne "w")
21969 { # "w" is default
21970 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021971 }
21972 if($ExtendedCheck) {
21973 @PARAMS = (@PARAMS, "-extended");
21974 }
21975 if($UserLang) {
21976 @PARAMS = (@PARAMS, "-lang", $UserLang);
21977 }
21978 if($TargetVersion{2}) {
21979 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
21980 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021981 if($BinaryOnly) {
21982 @PARAMS = (@PARAMS, "-binary");
21983 }
21984 if($SourceOnly) {
21985 @PARAMS = (@PARAMS, "-source");
21986 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021987 if($SortDump) {
21988 @PARAMS = (@PARAMS, "-sort");
21989 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021990 if($DumpFormat and $DumpFormat ne "perl") {
21991 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
21992 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021993 if($CheckHeadersOnly) {
21994 @PARAMS = (@PARAMS, "-headers-only");
21995 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021996 if($Debug)
21997 {
21998 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021999 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022000 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022001 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022002 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022003 exit(1);
22004 }
22005 else {
22006 exit(0);
22007 }
22008 }
22009 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022010
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022011 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022012 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22013 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022014 if($TargetTitle ne $TargetLibraryName) {
22015 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022016 }
22017 if($ShowRetVal) {
22018 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22019 }
22020 if($CrossGcc) {
22021 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22022 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022023 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22024 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022025 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022026 }
22027 if($ReportFormat and $ReportFormat ne "html")
22028 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022029 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22030 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022031 if($OutputReportPath) {
22032 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22033 }
22034 if($BinaryReportPath) {
22035 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22036 }
22037 if($SourceReportPath) {
22038 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22039 }
22040 if($LoggingPath) {
22041 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22042 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022043 if($CheckHeadersOnly) {
22044 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22045 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022046 if($BinaryOnly) {
22047 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22048 }
22049 if($SourceOnly) {
22050 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22051 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022052 if($Debug)
22053 {
22054 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22055 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022056 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022057 system("perl", $0, @CMP_PARAMS);
22058 exit($?>>8);
22059 }
22060 if(not $Descriptor{1}{"Dump"}
22061 or not $Descriptor{2}{"Dump"})
22062 { # need GCC toolchain to analyze
22063 # header files and libraries
22064 detect_default_paths("inc|lib|gcc");
22065 }
22066 if(not $Descriptor{1}{"Dump"})
22067 {
22068 if(not $CheckHeadersOnly) {
22069 readLibs(1);
22070 }
22071 if($CheckHeadersOnly) {
22072 setLanguage(1, "C++");
22073 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022074 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022075 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022076 }
22077 if(not $Descriptor{2}{"Dump"})
22078 {
22079 if(not $CheckHeadersOnly) {
22080 readLibs(2);
22081 }
22082 if($CheckHeadersOnly) {
22083 setLanguage(2, "C++");
22084 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022085 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022086 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022087 }
22088 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22089 { # support for old ABI dumps
22090 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022091 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022092 {
22093 $WORD_SIZE{1} = $WORD_SIZE{2};
22094 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22095 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022096 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022097 {
22098 $WORD_SIZE{2} = $WORD_SIZE{1};
22099 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22100 }
22101 }
22102 elsif(not $WORD_SIZE{1}
22103 and not $WORD_SIZE{2})
22104 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022105 $WORD_SIZE{1} = "4";
22106 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022107 }
22108 if($Descriptor{1}{"Dump"})
22109 { # support for old ABI dumps
22110 prepareTypes(1);
22111 }
22112 if($Descriptor{2}{"Dump"})
22113 { # support for old ABI dumps
22114 prepareTypes(2);
22115 }
22116 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22117 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22118 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022119 # process input data
22120 if($Descriptor{1}{"Headers"}
22121 and not $Descriptor{1}{"Dump"}) {
22122 readHeaders(1);
22123 }
22124 if($Descriptor{2}{"Headers"}
22125 and not $Descriptor{2}{"Dump"}) {
22126 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022127 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022128
22129 # clean memory
22130 %SystemHeaders = ();
22131 %mangled_name_gcc = ();
22132
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022133 prepareSymbols(1);
22134 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022135
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022136 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022137 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022138
22139 # Virtual Tables
22140 registerVTable(1);
22141 registerVTable(2);
22142
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022143 if(not checkDump(1, "1.22")
22144 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022145 { # support for old ABI dumps
22146 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22147 {
22148 if($ClassName=~/</)
22149 { # templates
22150 if(not defined $VirtualTable{1}{$ClassName})
22151 { # synchronize
22152 delete($VirtualTable{2}{$ClassName});
22153 }
22154 }
22155 }
22156 }
22157
22158 registerOverriding(1);
22159 registerOverriding(2);
22160
22161 setVirtFuncPositions(1);
22162 setVirtFuncPositions(2);
22163
22164 # Other
22165 addParamNames(1);
22166 addParamNames(2);
22167
22168 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022169}
22170
22171sub compareAPIs($)
22172{
22173 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022174
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022175 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022176 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022177
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022178 if($Level eq "Binary") {
22179 printMsg("INFO", "comparing ABIs ...");
22180 }
22181 else {
22182 printMsg("INFO", "comparing APIs ...");
22183 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022184
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022185 if($CheckHeadersOnly
22186 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022187 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022188 detectAdded_H($Level);
22189 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022190 }
22191 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022192 { # added/removed in libs
22193 detectAdded($Level);
22194 detectRemoved($Level);
22195 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022196
22197 mergeSymbols($Level);
22198 if(keys(%{$CheckedSymbols{$Level}})) {
22199 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022200 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022201
22202 $Cache{"mergeTypes"} = (); # free memory
22203
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022204 if($CheckHeadersOnly
22205 or $Level eq "Source")
22206 { # added/removed in headers
22207 mergeHeaders($Level);
22208 }
22209 else
22210 { # added/removed in libs
22211 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022212 }
22213}
22214
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022215sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022216{
22217 my %Opts = (
22218 "OStarget"=>$OStarget,
22219 "Debug"=>$Debug,
22220 "Quiet"=>$Quiet,
22221 "LogMode"=>$LogMode,
22222 "CheckHeadersOnly"=>$CheckHeadersOnly,
22223
22224 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022225 "GCC_PATH"=>$GCC_PATH,
22226 "TargetSysInfo"=>$TargetSysInfo,
22227 "CrossPrefix"=>$CrossPrefix,
22228 "TargetLibraryName"=>$TargetLibraryName,
22229 "CrossGcc"=>$CrossGcc,
22230 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022231 "NoStdInc"=>$NoStdInc,
22232
22233 "BinaryOnly" => $BinaryOnly,
22234 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022235 );
22236 return \%Opts;
22237}
22238
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022239sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022240{
22241 my %CODE_ERROR = reverse(%ERROR_CODE);
22242 return $CODE_ERROR{$_[0]};
22243}
22244
22245sub scenario()
22246{
22247 if($StdOut)
22248 { # enable quiet mode
22249 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022250 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022251 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022252 if(not $LogMode)
22253 { # default
22254 $LogMode = "w";
22255 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022256 if($UserLang)
22257 { # --lang=C++
22258 $UserLang = uc($UserLang);
22259 $COMMON_LANGUAGE{1}=$UserLang;
22260 $COMMON_LANGUAGE{2}=$UserLang;
22261 }
22262 if($LoggingPath)
22263 {
22264 $OutputLogPath{1} = $LoggingPath;
22265 $OutputLogPath{2} = $LoggingPath;
22266 if($Quiet) {
22267 $COMMON_LOG_PATH = $LoggingPath;
22268 }
22269 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022270 if($Quick) {
22271 $ADD_TMPL_INSTANCES = 0;
22272 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022273 if($OutputDumpPath)
22274 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022275 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022276 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22277 }
22278 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022279 if($BinaryOnly and $SourceOnly)
22280 { # both --binary and --source
22281 # is the default mode
22282 $DoubleReport = 1;
22283 $JoinReport = 0;
22284 $BinaryOnly = 0;
22285 $SourceOnly = 0;
22286 if($OutputReportPath)
22287 { # --report-path
22288 $DoubleReport = 0;
22289 $JoinReport = 1;
22290 }
22291 }
22292 elsif($BinaryOnly or $SourceOnly)
22293 { # --binary or --source
22294 $DoubleReport = 0;
22295 $JoinReport = 0;
22296 }
22297 if($UseXML)
22298 { # --xml option
22299 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022300 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022302 if($ReportFormat)
22303 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022304 $ReportFormat = lc($ReportFormat);
22305 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022306 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022307 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022308 if($ReportFormat eq "htm")
22309 { # HTM == HTML
22310 $ReportFormat = "html";
22311 }
22312 elsif($ReportFormat eq "xml")
22313 { # --report-format=XML equal to --xml
22314 $UseXML = 1;
22315 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022316 }
22317 else
22318 { # default: HTML
22319 $ReportFormat = "html";
22320 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022321 if($DumpFormat)
22322 { # validate
22323 $DumpFormat = lc($DumpFormat);
22324 if($DumpFormat!~/\A(xml|perl)\Z/) {
22325 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22326 }
22327 if($DumpFormat eq "xml")
22328 { # --dump-format=XML equal to --xml
22329 $UseXML = 1;
22330 }
22331 }
22332 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022333 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022334 $DumpFormat = "perl";
22335 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022336 if($Quiet and $LogMode!~/a|n/)
22337 { # --quiet log
22338 if(-f $COMMON_LOG_PATH) {
22339 unlink($COMMON_LOG_PATH);
22340 }
22341 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022342 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022343 $CheckUndefined = 1;
22344 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022345 if($TestTool and $UseDumps)
22346 { # --test && --use-dumps == --test-dump
22347 $TestDump = 1;
22348 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022349 if($Tolerant)
22350 { # enable all
22351 $Tolerance = 1234;
22352 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022353 if($Help)
22354 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022355 HELP_MESSAGE();
22356 exit(0);
22357 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022358 if($InfoMsg)
22359 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022360 INFO_MESSAGE();
22361 exit(0);
22362 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022363 if($ShowVersion)
22364 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022365 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 +040022366 exit(0);
22367 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022368 if($DumpVersion)
22369 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022370 printMsg("INFO", $TOOL_VERSION);
22371 exit(0);
22372 }
22373 if($ExtendedCheck) {
22374 $CheckHeadersOnly = 1;
22375 }
22376 if($SystemRoot_Opt)
22377 { # user defined root
22378 if(not -e $SystemRoot_Opt) {
22379 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22380 }
22381 $SystemRoot = $SystemRoot_Opt;
22382 $SystemRoot=~s/[\/]+\Z//g;
22383 if($SystemRoot) {
22384 $SystemRoot = get_abs_path($SystemRoot);
22385 }
22386 }
22387 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022388
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022389 if($SortDump)
22390 {
22391 $Data::Dumper::Useperl = 1;
22392 $Data::Dumper::Sortkeys = \&dump_sorting;
22393 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022394
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022395 if($TargetLibsPath)
22396 {
22397 if(not -f $TargetLibsPath) {
22398 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22399 }
22400 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22401 $TargetLibs{$Lib} = 1;
22402 }
22403 }
22404 if($TargetHeadersPath)
22405 { # --headers-list
22406 if(not -f $TargetHeadersPath) {
22407 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22408 }
22409 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22410 {
22411 $TargetHeaders{1}{$Header} = 1;
22412 $TargetHeaders{2}{$Header} = 1;
22413 }
22414 }
22415 if($TargetHeader)
22416 { # --header
22417 $TargetHeaders{1}{$TargetHeader} = 1;
22418 $TargetHeaders{2}{$TargetHeader} = 1;
22419 }
22420 if($TestTool
22421 or $TestDump)
22422 { # --test, --test-dump
22423 detect_default_paths("bin|gcc"); # to compile libs
22424 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022425 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022426 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022427 exit(0);
22428 }
22429 if($DumpSystem)
22430 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022431
22432 if(not $TargetSysInfo) {
22433 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22434 }
22435
22436 if(not -d $TargetSysInfo) {
22437 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22438 }
22439
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022440 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022441 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022442 { # system XML descriptor
22443 if(not -f $DumpSystem) {
22444 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22445 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022446
22447 my $SDesc = readFile($DumpSystem);
22448 if(my $RelDir = $RelativeDirectory{1}) {
22449 $SDesc =~ s/{RELPATH}/$RelDir/g;
22450 }
22451
22452 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022453 foreach (@{$Ret->{"Tools"}})
22454 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022455 push_U($SystemPaths{"bin"}, $_);
22456 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022457 }
22458 if($Ret->{"CrossPrefix"}) {
22459 $CrossPrefix = $Ret->{"CrossPrefix"};
22460 }
22461 }
22462 elsif($SystemRoot_Opt)
22463 { # -sysroot "/" option
22464 # default target: /usr/lib, /usr/include
22465 # search libs: /usr/lib and /lib
22466 if(not -e $SystemRoot."/usr/lib") {
22467 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22468 }
22469 if(not -e $SystemRoot."/lib") {
22470 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22471 }
22472 if(not -e $SystemRoot."/usr/include") {
22473 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22474 }
22475 readSystemDescriptor("
22476 <name>
22477 $DumpSystem
22478 </name>
22479 <headers>
22480 $SystemRoot/usr/include
22481 </headers>
22482 <libs>
22483 $SystemRoot/usr/lib
22484 </libs>
22485 <search_libs>
22486 $SystemRoot/lib
22487 </search_libs>");
22488 }
22489 else {
22490 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22491 }
22492 detect_default_paths("bin|gcc"); # to check symbols
22493 if($OStarget eq "windows")
22494 { # to run dumpbin.exe
22495 # and undname.exe
22496 check_win32_env();
22497 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022498 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022499 exit(0);
22500 }
22501 if($CmpSystems)
22502 { # --cmp-systems
22503 detect_default_paths("bin"); # to extract dumps
22504 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022505 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022506 exit(0);
22507 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022508 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022509 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022510 }
22511 else
22512 { # validate library name
22513 if($TargetLibraryName=~/[\*\/\\]/) {
22514 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22515 }
22516 }
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022517 if(not $TargetTitle) {
22518 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022519 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022520
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022521 if($SymbolsListPath)
22522 {
22523 if(not -f $SymbolsListPath) {
22524 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22525 }
22526 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22527 $SymbolsList{$Interface} = 1;
22528 }
22529 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022530 if($TypesListPath)
22531 {
22532 if(not -f $TypesListPath) {
22533 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22534 }
22535 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22536 $TypesList{$Type} = 1;
22537 }
22538 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022539 if($SkipSymbolsListPath)
22540 {
22541 if(not -f $SkipSymbolsListPath) {
22542 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22543 }
22544 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022545 $SkipSymbols{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022546 }
22547 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022548 if($SkipHeadersPath)
22549 {
22550 if(not -f $SkipHeadersPath) {
22551 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22552 }
22553 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022554 { # register for both versions
22555 $SkipHeadersList{1}{$Path} = 1;
22556 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022557 my ($CPath, $Type) = classifyPath($Path);
22558 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022559 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022560 }
22561 }
22562 if($ParamNamesPath)
22563 {
22564 if(not -f $ParamNamesPath) {
22565 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22566 }
22567 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22568 {
22569 if($Line=~s/\A(\w+)\;//)
22570 {
22571 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022572 if($Line=~/;(\d+);/)
22573 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022574 while($Line=~s/(\d+);(\w+)//) {
22575 $AddIntParams{$Interface}{$1}=$2;
22576 }
22577 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022578 else
22579 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022580 my $Num = 0;
22581 foreach my $Name (split(/;/, $Line)) {
22582 $AddIntParams{$Interface}{$Num++}=$Name;
22583 }
22584 }
22585 }
22586 }
22587 }
22588 if($AppPath)
22589 {
22590 if(not -f $AppPath) {
22591 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22592 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022593
22594 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022595 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022596 $SymbolsList_App{$Interface} = 1;
22597 }
22598 }
22599 if($DumpAPI)
22600 { # --dump-abi
22601 # make an API dump
22602 create_ABI_Dump();
22603 exit($COMPILE_ERRORS);
22604 }
22605 # default: compare APIs
22606 # -d1 <path>
22607 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022608 compareInit();
22609 if($JoinReport or $DoubleReport)
22610 {
22611 compareAPIs("Binary");
22612 compareAPIs("Source");
22613 }
22614 elsif($BinaryOnly) {
22615 compareAPIs("Binary");
22616 }
22617 elsif($SourceOnly) {
22618 compareAPIs("Source");
22619 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022620 exitReport();
22621}
22622
22623scenario();