blob: 0124e6bc1f19c78d553823f2139d0964877c1b50 [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 Ponomarenko8bfdcd82015-09-08 17:58:01 +03008# Copyright (C) 2011-2012 ROSA Laboratory
9# Copyright (C) 2012-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 Ponomarenko8bfdcd82015-09-08 17:58:01 +0300406 -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 Ponomarenko8bfdcd82015-09-08 17:58:01 +0300409 -gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400410 GCC toolchain prefix.
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300411
412 -gcc-options OPTS
413 Additional compiler options.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400414
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400415 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400416 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400417 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400418
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400419 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400420 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200421 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400422
423 In general case you should specify it in the XML-descriptor:
424 <version>
425 VERSION
426 </version>
427
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400428 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400429 Specify 2nd library version outside the descriptor.
430
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400431 -vnum NUM
432 Specify the library version in the generated ABI dump. The <version> section
433 of the input XML descriptor will be overwritten in this case.
434
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400435 -s|-strict
436 Treat all compatibility warnings as problems. Add a number of \"Low\"
437 severity problems to the return value of the tool.
438
439 -headers-only
440 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
441 provide a low quality compatibility report with false positives and
442 without detecting of added/removed symbols.
443
444 Alternatively you can write \"none\" word to the <libs> section
445 in the XML-descriptor:
446 <libs>
447 none
448 </libs>
449
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400450 -show-retval
451 Show the symbol's return type in the report.
452
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400453 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300454 This option allows to specify a file with a list of symbols (mangled
455 names in C++) that should be checked. Other symbols will not be checked.
456
457 -types-list PATH
458 This option allows to specify a file with a list of types that should
459 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400460
461 -skip-symbols PATH
462 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400463
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400464 -headers-list PATH
465 The file with a list of headers, that should be checked/dumped.
466
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400467 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400468 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400469
470 -header NAME
471 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400472
473 -use-dumps
474 Make dumps for two versions of a library and compare dumps. This should
475 increase the performance of the tool and decrease the system memory usage.
476
477 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400478 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400479
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400480 -dump-system NAME -sysroot DIR
481 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400482 create XML descriptors and make ABI dumps for each library. The result
483 set of ABI dumps can be compared (--cmp-systems) with the other one
484 created for other version of operating system in order to check them for
485 compatibility. Do not forget to specify -cross-gcc option if your target
486 system requires some specific version of GCC compiler (different from
487 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400488 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400489
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400490 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400491 The same as the previous option but takes an XML descriptor of the target
492 system as input, where you should describe it:
493
494 /* Primary sections */
495
496 <name>
497 /* Name of the system */
498 </name>
499
500 <headers>
501 /* The list of paths to header files and/or
502 directories with header files, one per line */
503 </headers>
504
505 <libs>
506 /* The list of paths to shared libraries and/or
507 directories with shared libraries, one per line */
508 </libs>
509
510 /* Optional sections */
511
512 <search_headers>
513 /* List of directories to be searched
514 for header files to automatically
515 generate include paths, one per line */
516 </search_headers>
517
518 <search_libs>
519 /* List of directories to be searched
520 for shared libraries to resolve
521 dependencies, one per line */
522 </search_libs>
523
524 <tools>
525 /* List of directories with tools used
526 for analysis (GCC toolchain), one per line */
527 </tools>
528
529 <cross_prefix>
530 /* GCC toolchain prefix.
531 Examples:
532 arm-linux-gnueabi
533 arm-none-symbianelf */
534 </cross_prefix>
535
536 <gcc_options>
537 /* Additional GCC options, one per line */
538 </gcc_options>
539
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400540 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300541 This option should be used with -dump-system option to dump
542 ABI of operating systems and configure the dumping process.
543 You can find a sample in the package:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400544 modules/Targets/{unix, symbian, windows}
545
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400546 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400547 Compare two system ABI dumps. Create compatibility reports for each
548 library and the common HTML report including the summary of test
549 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400550 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400551
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400552 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400553 The file with a list of libraries, that should be dumped by
554 the -dump-system option or should be checked by the -cmp-systems option.
555
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400556 -ext|-extended
557 If your library A is supposed to be used by other library B and you
558 want to control the ABI of B, then you should enable this option. The
559 tool will check for changes in all data types, even if they are not
560 used by any function in the library A. Such data types are not part
561 of the A library ABI, but may be a part of the ABI of the B library.
562
563 The short scheme is:
564 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
565
566 -q|-quiet
567 Print all messages to the file instead of stdout and stderr.
568 Default path (can be changed by -log-path option):
569 $COMMON_LOG_PATH
570
571 -stdout
572 Print analysis results (compatibility reports and ABI dumps) to stdout
573 instead of creating a file. This would allow piping data to other programs.
574
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400575 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400576 Change format of compatibility report.
577 Formats:
578 htm - HTML format (default)
579 xml - XML format
580
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400581 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400582 Change format of ABI dump.
583 Formats:
584 perl - Data::Dumper format (default)
585 xml - XML format
586
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400587 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400588 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400589
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400590 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400591 Set library language (C or C++). You can use this option if the tool
592 cannot auto-detect a language. This option may be useful for checking
593 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400594
595 -arch ARCH
596 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
597 ect.). The option is useful if the tool cannot detect correct architecture
598 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400599
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400600 -binary|-bin|-abi
601 Show \"Binary\" compatibility problems only.
602 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400603 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400604
605 -source|-src|-api
606 Show \"Source\" compatibility problems only.
607 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400608 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400609
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400610 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400611 The maximum number of affected symbols listed under the description
612 of the changed type in the report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400613
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400614OTHER OPTIONS:
615 -test
616 Run internal tests. Create two binary incompatible versions of a sample
617 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300618 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400619
620 -test-dump
621 Test ability to create, read and compare ABI dumps.
622
623 -debug
624 Debugging mode. Print debug info on the screen. Save intermediate
625 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400626 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400627
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400628 Also consider using --dump option for debugging the tool.
629
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400630 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400631 If your header files are written in C language and can be compiled
632 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
633 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400634
635 -cpp-incompatible
636 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400637
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400638 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400639 Path to file with the function parameter names. It can be used
640 for improving report view if the library header files have no
641 parameter names. File format:
642
643 func1;param1;param2;param3 ...
644 func2;param1;param2;param3 ...
645 ...
646
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400647 -relpath PATH
648 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400649 for dumping the library ABI (see -dump option).
650
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400651 -relpath1 PATH
652 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400653
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400654 -relpath2 PATH
655 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400656
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400657 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400658 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400659 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400660 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400661
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400662 -sort
663 Enable sorting of data in ABI dumps.
664
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400665 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400666 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400667 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400668 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400669
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400670 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400671 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400672 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400673 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400674
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400675 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400676 Path to \"Source\" compatibility report.
677 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400678 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400679
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400680 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400681 Log path for all messages.
682 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400683 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400684
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400685 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400686 Log path for 1st version of a library.
687 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400688 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400689
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400691 Log path for 2nd version of a library.
692 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400693 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400694
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400695 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400696 Change logging mode.
697 Modes:
698 w - overwrite old logs (default)
699 a - append old logs
700 n - do not write any logs
701
702 -list-affected
703 Generate file with the list of incompatible
704 symbols beside the HTML compatibility report.
705 Use 'c++filt \@file' command from GNU binutils
706 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400707 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400708 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400709 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400710
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400711 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400712 The component name in the title and summary of the HTML report.
713 Default:
714 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300715
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300716 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400717 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400718 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400719
720 -extra-info DIR
721 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400722
723 -extra-dump
724 Create extended ABI dump containing all symbols
725 from the translation unit.
726
727 -force
728 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400729
730 -tolerance LEVEL
731 Apply a set of heuristics to successfully compile input
732 header files. You can enable several tolerance levels by
733 joining them into one string (e.g. 13, 124, etc.).
734 Levels:
735 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
736 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
737 3 - skip headers that iclude non-Linux headers
738 4 - skip headers included by others
739
740 -tolerant
741 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400742
743 -check
744 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400745
746 -quick
747 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400748
749 -skip-internal PATTERN
750 Do not check internal interfaces matched by the pattern.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400751
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400752REPORT:
753 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400754 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400755
756 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400757 logs/LIB_NAME/V1/log.txt
758 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400759
760EXIT CODES:
761 0 - Compatible. The tool has run without any errors.
762 non-zero - Incompatible or the tool has run with errors.
763
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400764MORE INFORMATION:
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300765 ".$HomePage."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400766}
767
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400768my %Operator_Indication = (
769 "not" => "~",
770 "assign" => "=",
771 "andassign" => "&=",
772 "orassign" => "|=",
773 "xorassign" => "^=",
774 "or" => "|",
775 "xor" => "^",
776 "addr" => "&",
777 "and" => "&",
778 "lnot" => "!",
779 "eq" => "==",
780 "ne" => "!=",
781 "lt" => "<",
782 "lshift" => "<<",
783 "lshiftassign" => "<<=",
784 "rshiftassign" => ">>=",
785 "call" => "()",
786 "mod" => "%",
787 "modassign" => "%=",
788 "subs" => "[]",
789 "land" => "&&",
790 "lor" => "||",
791 "rshift" => ">>",
792 "ref" => "->",
793 "le" => "<=",
794 "deref" => "*",
795 "mult" => "*",
796 "preinc" => "++",
797 "delete" => " delete",
798 "vecnew" => " new[]",
799 "vecdelete" => " delete[]",
800 "predec" => "--",
801 "postinc" => "++",
802 "postdec" => "--",
803 "plusassign" => "+=",
804 "plus" => "+",
805 "minus" => "-",
806 "minusassign" => "-=",
807 "gt" => ">",
808 "ge" => ">=",
809 "new" => " new",
810 "multassign" => "*=",
811 "divassign" => "/=",
812 "div" => "/",
813 "neg" => "-",
814 "pos" => "+",
815 "memref" => "->*",
816 "compound" => "," );
817
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400818my %UnknownOperator;
819
820my %NodeType= (
821 "array_type" => "Array",
822 "binfo" => "Other",
823 "boolean_type" => "Intrinsic",
824 "complex_type" => "Intrinsic",
825 "const_decl" => "Other",
826 "enumeral_type" => "Enum",
827 "field_decl" => "Other",
828 "function_decl" => "Other",
829 "function_type" => "FunctionType",
830 "identifier_node" => "Other",
831 "integer_cst" => "Other",
832 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400833 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400834 "method_type" => "MethodType",
835 "namespace_decl" => "Other",
836 "parm_decl" => "Other",
837 "pointer_type" => "Pointer",
838 "real_cst" => "Other",
839 "real_type" => "Intrinsic",
840 "record_type" => "Struct",
841 "reference_type" => "Ref",
842 "string_cst" => "Other",
843 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400844 "template_type_parm" => "TemplateParam",
845 "typename_type" => "TypeName",
846 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400847 "tree_list" => "Other",
848 "tree_vec" => "Other",
849 "type_decl" => "Other",
850 "union_type" => "Union",
851 "var_decl" => "Other",
852 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400853 "nop_expr" => "Other", #
854 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400855 "offset_type" => "Other" );
856
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400857my %CppKeywords_C = map {$_=>1} (
858 # C++ 2003 keywords
859 "public",
860 "protected",
861 "private",
862 "default",
863 "template",
864 "new",
865 #"asm",
866 "dynamic_cast",
867 "auto",
868 "try",
869 "namespace",
870 "typename",
871 "using",
872 "reinterpret_cast",
873 "friend",
874 "class",
875 "virtual",
876 "const_cast",
877 "mutable",
878 "static_cast",
879 "export",
880 # C++0x keywords
881 "noexcept",
882 "nullptr",
883 "constexpr",
884 "static_assert",
885 "explicit",
886 # cannot be used as a macro name
887 # as it is an operator in C++
888 "and",
889 #"and_eq",
890 "not",
891 #"not_eq",
892 "or"
893 #"or_eq",
894 #"bitand",
895 #"bitor",
896 #"xor",
897 #"xor_eq",
898 #"compl"
899);
900
901my %CppKeywords_F = map {$_=>1} (
902 "delete",
903 "catch",
904 "alignof",
905 "thread_local",
906 "decltype",
907 "typeid"
908);
909
910my %CppKeywords_O = map {$_=>1} (
911 "bool",
912 "register",
913 "inline",
914 "operator"
915);
916
917my %CppKeywords_A = map {$_=>1} (
918 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400919 "throw",
920 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400921);
922
923foreach (keys(%CppKeywords_C),
924keys(%CppKeywords_F),
925keys(%CppKeywords_O)) {
926 $CppKeywords_A{$_}=1;
927}
928
929# Header file extensions as described by gcc
930my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
931
932my %IntrinsicMangling = (
933 "void" => "v",
934 "bool" => "b",
935 "wchar_t" => "w",
936 "char" => "c",
937 "signed char" => "a",
938 "unsigned char" => "h",
939 "short" => "s",
940 "unsigned short" => "t",
941 "int" => "i",
942 "unsigned int" => "j",
943 "long" => "l",
944 "unsigned long" => "m",
945 "long long" => "x",
946 "__int64" => "x",
947 "unsigned long long" => "y",
948 "__int128" => "n",
949 "unsigned __int128" => "o",
950 "float" => "f",
951 "double" => "d",
952 "long double" => "e",
953 "__float80" => "e",
954 "__float128" => "g",
955 "..." => "z"
956);
957
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400958my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
959
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400960my %StdcxxMangling = (
961 "3std"=>"St",
962 "3std9allocator"=>"Sa",
963 "3std12basic_string"=>"Sb",
964 "3std12basic_stringIcE"=>"Ss",
965 "3std13basic_istreamIcE"=>"Si",
966 "3std13basic_ostreamIcE"=>"So",
967 "3std14basic_iostreamIcE"=>"Sd"
968);
969
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +0400970my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400971my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
972
973my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400974my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400975
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400976my %ConstantSuffix = (
977 "unsigned int"=>"u",
978 "long"=>"l",
979 "unsigned long"=>"ul",
980 "long long"=>"ll",
981 "unsigned long long"=>"ull"
982);
983
984my %ConstantSuffixR =
985reverse(%ConstantSuffix);
986
987my %OperatorMangling = (
988 "~" => "co",
989 "=" => "aS",
990 "|" => "or",
991 "^" => "eo",
992 "&" => "an",#ad (addr)
993 "==" => "eq",
994 "!" => "nt",
995 "!=" => "ne",
996 "<" => "lt",
997 "<=" => "le",
998 "<<" => "ls",
999 "<<=" => "lS",
1000 ">" => "gt",
1001 ">=" => "ge",
1002 ">>" => "rs",
1003 ">>=" => "rS",
1004 "()" => "cl",
1005 "%" => "rm",
1006 "[]" => "ix",
1007 "&&" => "aa",
1008 "||" => "oo",
1009 "*" => "ml",#de (deref)
1010 "++" => "pp",#
1011 "--" => "mm",#
1012 "new" => "nw",
1013 "delete" => "dl",
1014 "new[]" => "na",
1015 "delete[]" => "da",
1016 "+=" => "pL",
1017 "+" => "pl",#ps (pos)
1018 "-" => "mi",#ng (neg)
1019 "-=" => "mI",
1020 "*=" => "mL",
1021 "/=" => "dV",
1022 "&=" => "aN",
1023 "|=" => "oR",
1024 "%=" => "rM",
1025 "^=" => "eO",
1026 "/" => "dv",
1027 "->*" => "pm",
1028 "->" => "pt",#rf (ref)
1029 "," => "cm",
1030 "?" => "qu",
1031 "." => "dt",
1032 "sizeof"=> "sz"#st
1033);
1034
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001035my %Intrinsic_Keywords = map {$_=>1} (
1036 "true",
1037 "false",
1038 "_Bool",
1039 "_Complex",
1040 "const",
1041 "int",
1042 "long",
1043 "void",
1044 "short",
1045 "float",
1046 "volatile",
1047 "restrict",
1048 "unsigned",
1049 "signed",
1050 "char",
1051 "double",
1052 "class",
1053 "struct",
1054 "union",
1055 "enum"
1056);
1057
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001058my %GlibcHeader = map {$_=>1} (
1059 "aliases.h",
1060 "argp.h",
1061 "argz.h",
1062 "assert.h",
1063 "cpio.h",
1064 "ctype.h",
1065 "dirent.h",
1066 "envz.h",
1067 "errno.h",
1068 "error.h",
1069 "execinfo.h",
1070 "fcntl.h",
1071 "fstab.h",
1072 "ftw.h",
1073 "glob.h",
1074 "grp.h",
1075 "iconv.h",
1076 "ifaddrs.h",
1077 "inttypes.h",
1078 "langinfo.h",
1079 "limits.h",
1080 "link.h",
1081 "locale.h",
1082 "malloc.h",
1083 "math.h",
1084 "mntent.h",
1085 "monetary.h",
1086 "nl_types.h",
1087 "obstack.h",
1088 "printf.h",
1089 "pwd.h",
1090 "regex.h",
1091 "sched.h",
1092 "search.h",
1093 "setjmp.h",
1094 "shadow.h",
1095 "signal.h",
1096 "spawn.h",
1097 "stdarg.h",
1098 "stdint.h",
1099 "stdio.h",
1100 "stdlib.h",
1101 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001102 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001103 "tar.h",
1104 "termios.h",
1105 "time.h",
1106 "ulimit.h",
1107 "unistd.h",
1108 "utime.h",
1109 "wchar.h",
1110 "wctype.h",
1111 "wordexp.h" );
1112
1113my %GlibcDir = map {$_=>1} (
1114 "arpa",
1115 "bits",
1116 "gnu",
1117 "netinet",
1118 "net",
1119 "nfs",
1120 "rpc",
1121 "sys",
1122 "linux" );
1123
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001124my %WinHeaders = map {$_=>1} (
1125 "dos.h",
1126 "process.h",
1127 "winsock.h",
1128 "config-win.h",
1129 "mem.h",
1130 "windows.h",
1131 "winsock2.h",
1132 "crtdbg.h",
1133 "ws2tcpip.h"
1134);
1135
1136my %ObsoleteHeaders = map {$_=>1} (
1137 "iostream.h",
1138 "fstream.h"
1139);
1140
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001141my %AlienHeaders = map {$_=>1} (
1142 # Solaris
1143 "thread.h",
1144 "sys/atomic.h",
1145 # HPUX
1146 "sys/stream.h",
1147 # Symbian
1148 "AknDoc.h",
1149 # Atari ST
1150 "ext.h",
1151 "tos.h",
1152 # MS-DOS
1153 "alloc.h",
1154 # Sparc
1155 "sys/atomic.h"
1156);
1157
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001158my %ConfHeaders = map {$_=>1} (
1159 "atomic",
1160 "conf.h",
1161 "config.h",
1162 "configure.h",
1163 "build.h",
1164 "setup.h"
1165);
1166
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001167my %LocalIncludes = map {$_=>1} (
1168 "/usr/local/include",
1169 "/usr/local" );
1170
1171my %OS_AddPath=(
1172# These paths are needed if the tool cannot detect them automatically
1173 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001174 "include"=>[
1175 "/Library",
1176 "/Developer/usr/include"
1177 ],
1178 "lib"=>[
1179 "/Library",
1180 "/Developer/usr/lib"
1181 ],
1182 "bin"=>[
1183 "/Developer/usr/bin"
1184 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001185 },
1186 "beos"=>{
1187 # Haiku has GCC 2.95.3 by default
1188 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001189 "include"=>[
1190 "/boot/common",
1191 "/boot/develop"
1192 ],
1193 "lib"=>[
1194 "/boot/common/lib",
1195 "/boot/system/lib",
1196 "/boot/apps"
1197 ],
1198 "bin"=>[
1199 "/boot/common/bin",
1200 "/boot/system/bin",
1201 "/boot/develop/abi"
1202 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001203 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001204);
1205
1206my %Slash_Type=(
1207 "default"=>"/",
1208 "windows"=>"\\"
1209);
1210
1211my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1212
1213# Global Variables
1214my %COMMON_LANGUAGE=(
1215 1 => "C",
1216 2 => "C" );
1217
1218my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001219my $MAX_CPPFILT_FILE_SIZE = 50000;
1220my $CPPFILT_SUPPORT_FILE;
1221
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001222my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1223
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001224my $STDCXX_TESTING = 0;
1225my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001226my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001227
1228my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001229
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001230my $TargetComponent;
1231
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001232my $CheckUndefined = 0;
1233
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001234# Set Target Component Name
1235if($TargetComponent_Opt) {
1236 $TargetComponent = lc($TargetComponent_Opt);
1237}
1238else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001239{ # default: library
1240 # other components: header, system, ...
1241 $TargetComponent = "library";
1242}
1243
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001244my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001245
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001246my $SystemRoot;
1247
1248my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001249my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001250my %LOG_PATH;
1251my %DEBUG_PATH;
1252my %Cache;
1253my %LibInfo;
1254my $COMPILE_ERRORS = 0;
1255my %CompilerOptions;
1256my %CheckedDyLib;
1257my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1258
1259# Constants (#defines)
1260my %Constants;
1261my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001262my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001263
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001264# Extra Info
1265my %SymbolHeader;
1266my %KnownLibs;
1267
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001268# Templates
1269my %TemplateInstance;
1270my %BasicTemplate;
1271my %TemplateArg;
1272my %TemplateDecl;
1273my %TemplateMap;
1274
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001275# Types
1276my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001277my %SkipTypes = (
1278 "1"=>{},
1279 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001280my %CheckedTypes;
1281my %TName_Tid;
1282my %EnumMembName_Id;
1283my %NestedNameSpaces = (
1284 "1"=>{},
1285 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001286my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001287my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001288my %ClassVTable;
1289my %ClassVTable_Content;
1290my %VTableClass;
1291my %AllocableClass;
1292my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001293my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001294my %Class_SubClasses;
1295my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001296my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001297my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001298
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001299my %CheckedTypeInfo;
1300
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001301# Typedefs
1302my %Typedef_BaseName;
1303my %Typedef_Tr;
1304my %Typedef_Eq;
1305my %StdCxxTypedef;
1306my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001307my %MissedBase;
1308my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001309my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001310
1311# Symbols
1312my %SymbolInfo;
1313my %tr_name;
1314my %mangled_name_gcc;
1315my %mangled_name;
1316my %SkipSymbols = (
1317 "1"=>{},
1318 "2"=>{} );
1319my %SkipNameSpaces = (
1320 "1"=>{},
1321 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001322my %AddNameSpaces = (
1323 "1"=>{},
1324 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001325my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001326my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001327my %SymbolsList_App;
1328my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001329my %Symbol_Library = (
1330 "1"=>{},
1331 "2"=>{} );
1332my %Library_Symbol = (
1333 "1"=>{},
1334 "2"=>{} );
1335my %DepSymbol_Library = (
1336 "1"=>{},
1337 "2"=>{} );
1338my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001339 "1"=>{},
1340 "2"=>{} );
1341my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001342my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001343my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001344my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001345my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001346my %Library_Needed= (
1347 "1"=>{},
1348 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001349
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001350# Extra Info
1351my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001352my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001353
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001354# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001355my %Include_Preamble = (
1356 "1"=>[],
1357 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001358my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001359my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001360my %HeaderName_Paths;
1361my %Header_Dependency;
1362my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001363my %Include_Paths = (
1364 "1"=>[],
1365 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001366my %INC_PATH_AUTODETECT = (
1367 "1"=>1,
1368 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001369my %Add_Include_Paths = (
1370 "1"=>[],
1371 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001372my %Skip_Include_Paths;
1373my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001374my %Header_ErrorRedirect;
1375my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001376my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001377my %Header_ShouldNotBeUsed;
1378my %RecursiveIncludes;
1379my %Header_Include_Prefix;
1380my %SkipHeaders;
1381my %SkipHeadersList=(
1382 "1"=>{},
1383 "2"=>{} );
1384my %SkipLibs;
1385my %Include_Order;
1386my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001387my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001388my %TUnit_Funcs;
1389my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001390
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001391my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001392 "1"=>0,
1393 "2"=>0 );
1394my %AutoPreambleMode = (
1395 "1"=>0,
1396 "2"=>0 );
1397my %MinGWMode = (
1398 "1"=>0,
1399 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001400my %Cpp0xMode = (
1401 "1"=>0,
1402 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001403
1404# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001405my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001406my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001407my %RegisteredSONAMEs;
1408my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001409
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001410my %CheckedArch;
1411
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001412# System Objects
1413my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001414my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001415my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001416
1417# System Headers
1418my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001419my @DefaultCppPaths;
1420my @DefaultGccPaths;
1421my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001422my %DefaultCppHeader;
1423my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001424my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001425
1426# Merging
1427my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001428my $Version;
1429my %AddedInt;
1430my %RemovedInt;
1431my %AddedInt_Virt;
1432my %RemovedInt_Virt;
1433my %VirtualReplacement;
1434my %ChangedTypedef;
1435my %CompatRules;
1436my %IncompleteRules;
1437my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001438my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001439my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001440my %ReturnedClass;
1441my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001442my %SourceAlternative;
1443my %SourceAlternative_B;
1444my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001445my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001446
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001447# Calling Conventions
1448my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001449 1=>{ "R"=>0, "P"=>0 },
1450 2=>{ "R"=>0, "P"=>0 }
1451);
1452
1453# ABI Dump
1454my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001455
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001456# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001457my %TargetLibs;
1458my %TargetHeaders;
1459
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001460# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001461my $OStarget = $OSgroup;
1462my %TargetTools;
1463
1464# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001465my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001466
1467# Recursion locks
1468my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001469my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001470my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001471my @RecurInclude;
1472my @RecurConstant;
1473
1474# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001475my %SystemPaths = (
1476 "include"=>[],
1477 "lib"=>[],
1478 "bin"=>[]
1479);
1480my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001481my $GCC_PATH;
1482
1483# Symbols versioning
1484my %SymVer = (
1485 "1"=>{},
1486 "2"=>{} );
1487
1488# Problem descriptions
1489my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001490my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001491my %TotalAffected;
1492
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001493# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001494my $ContentID = 1;
1495my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1496my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1497my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1498my $ContentSpanEnd = "</span>\n";
1499my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1500my $ContentDivEnd = "</div>\n";
1501my $Content_Counter = 0;
1502
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001503# Modes
1504my $JoinReport = 1;
1505my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001506
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001507my %Severity_Val=(
1508 "High"=>3,
1509 "Medium"=>2,
1510 "Low"=>1,
1511 "Safe"=>-1
1512);
1513
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001514sub get_Modules()
1515{
1516 my $TOOL_DIR = get_dirname($0);
1517 if(not $TOOL_DIR)
1518 { # patch for MS Windows
1519 $TOOL_DIR = ".";
1520 }
1521 my @SEARCH_DIRS = (
1522 # tool's directory
1523 abs_path($TOOL_DIR),
1524 # relative path to modules
1525 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001526 # install path
1527 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001528 );
1529 foreach my $DIR (@SEARCH_DIRS)
1530 {
1531 if(not is_abs($DIR))
1532 { # relative path
1533 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1534 }
1535 if(-d $DIR."/modules") {
1536 return $DIR."/modules";
1537 }
1538 }
1539 exitStatus("Module_Error", "can't find modules");
1540}
1541
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001542my %LoadedModules = ();
1543
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001544sub loadModule($)
1545{
1546 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001547 if(defined $LoadedModules{$Name}) {
1548 return;
1549 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001550 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1551 if(not -f $Path) {
1552 exitStatus("Module_Error", "can't access \'$Path\'");
1553 }
1554 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001555 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001556}
1557
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001558sub readModule($$)
1559{
1560 my ($Module, $Name) = @_;
1561 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1562 if(not -f $Path) {
1563 exitStatus("Module_Error", "can't access \'$Path\'");
1564 }
1565 return readFile($Path);
1566}
1567
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001568sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001569{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001570 my $Number = $_[0];
1571 if(not $Number) {
1572 $Number = 1;
1573 }
1574 else {
1575 $Number = int($Number)+1;
1576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001577 if($Number>3) {
1578 return $Number."th";
1579 }
1580 elsif($Number==1) {
1581 return "1st";
1582 }
1583 elsif($Number==2) {
1584 return "2nd";
1585 }
1586 elsif($Number==3) {
1587 return "3rd";
1588 }
1589 else {
1590 return $Number;
1591 }
1592}
1593
1594sub search_Tools($)
1595{
1596 my $Name = $_[0];
1597 return "" if(not $Name);
1598 if(my @Paths = keys(%TargetTools))
1599 {
1600 foreach my $Path (@Paths)
1601 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001602 if(-f join_P($Path, $Name)) {
1603 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001604 }
1605 if($CrossPrefix)
1606 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001607 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001608 if(-f $Candidate) {
1609 return $Candidate;
1610 }
1611 }
1612 }
1613 }
1614 else {
1615 return "";
1616 }
1617}
1618
1619sub synch_Cmd($)
1620{
1621 my $Name = $_[0];
1622 if(not $GCC_PATH)
1623 { # GCC was not found yet
1624 return "";
1625 }
1626 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001627 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001628 return $Candidate;
1629 }
1630 return "";
1631}
1632
1633sub get_CmdPath($)
1634{
1635 my $Name = $_[0];
1636 return "" if(not $Name);
1637 if(defined $Cache{"get_CmdPath"}{$Name}) {
1638 return $Cache{"get_CmdPath"}{$Name};
1639 }
1640 my %BinUtils = map {$_=>1} (
1641 "c++filt",
1642 "objdump",
1643 "readelf"
1644 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001645 if($BinUtils{$Name} and $GCC_PATH)
1646 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001647 if(my $Dir = get_dirname($GCC_PATH)) {
1648 $TargetTools{$Dir}=1;
1649 }
1650 }
1651 my $Path = search_Tools($Name);
1652 if(not $Path and $OSgroup eq "windows") {
1653 $Path = search_Tools($Name.".exe");
1654 }
1655 if(not $Path and $BinUtils{$Name})
1656 {
1657 if($CrossPrefix)
1658 { # user-defined prefix
1659 $Path = search_Cmd($CrossPrefix."-".$Name);
1660 }
1661 }
1662 if(not $Path and $BinUtils{$Name})
1663 {
1664 if(my $Candidate = synch_Cmd($Name))
1665 { # synch with GCC
1666 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001667 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001668 if(-f $Candidate) {
1669 $Path = $Candidate;
1670 }
1671 }
1672 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001673 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001674 $Path = $Candidate;
1675 }
1676 }
1677 }
1678 if(not $Path) {
1679 $Path = search_Cmd($Name);
1680 }
1681 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001682 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001683 $Path=search_Cmd($Name.".exe");
1684 }
1685 if($Path=~/\s/) {
1686 $Path = "\"".$Path."\"";
1687 }
1688 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1689}
1690
1691sub search_Cmd($)
1692{
1693 my $Name = $_[0];
1694 return "" if(not $Name);
1695 if(defined $Cache{"search_Cmd"}{$Name}) {
1696 return $Cache{"search_Cmd"}{$Name};
1697 }
1698 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1699 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1700 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001701 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001702 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001703 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001704 if(-f $CmdPath)
1705 {
1706 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001707 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001708 }
1709 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1710 }
1711 }
1712 return ($Cache{"search_Cmd"}{$Name} = "");
1713}
1714
1715sub get_CmdPath_Default($)
1716{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001717 return "" if(not $_[0]);
1718 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1719 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001720 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001721 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1722}
1723
1724sub get_CmdPath_Default_I($)
1725{ # search in PATH
1726 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001727 if($Name=~/find/)
1728 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001729 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001730 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001731 }
1732 }
1733 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001734 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001735 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001736 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001737 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001738 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001739 if($OSgroup eq "windows")
1740 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001741 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001742 return $Name;
1743 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001744 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001745 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001746 {
1747 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001748 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001749 }
1750 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001751 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001752}
1753
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001754sub classifyPath($)
1755{
1756 my $Path = $_[0];
1757 if($Path=~/[\*\[]/)
1758 { # wildcard
1759 $Path=~s/\*/.*/g;
1760 $Path=~s/\\/\\\\/g;
1761 return ($Path, "Pattern");
1762 }
1763 elsif($Path=~/[\/\\]/)
1764 { # directory or relative path
1765 return (path_format($Path, $OSgroup), "Path");
1766 }
1767 else {
1768 return ($Path, "Name");
1769 }
1770}
1771
1772sub readDescriptor($$)
1773{
1774 my ($LibVersion, $Content) = @_;
1775 return if(not $LibVersion);
1776 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1777 if(not $Content) {
1778 exitStatus("Error", "$DName is empty");
1779 }
1780 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001781 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001782 }
1783 $Content=~s/\/\*(.|\n)+?\*\///g;
1784 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001785
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001786 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1787 if($TargetVersion{$LibVersion}) {
1788 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1789 }
1790 if(not $Descriptor{$LibVersion}{"Version"}) {
1791 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1792 }
1793 if($Content=~/{RELPATH}/)
1794 {
1795 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1796 $Content =~ s/{RELPATH}/$RelDir/g;
1797 }
1798 else
1799 {
1800 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1801 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1802 }
1803 }
1804
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001805 my $DHeaders = parseTag(\$Content, "headers");
1806 if(not $DHeaders) {
1807 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1808 }
1809 elsif(lc($DHeaders) ne "none")
1810 { # append the descriptor headers list
1811 if($Descriptor{$LibVersion}{"Headers"})
1812 { # multiple descriptors
1813 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001814 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001815 else {
1816 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1817 }
1818 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1819 {
1820 if(not -e $Path) {
1821 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001822 }
1823 }
1824 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001825
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001826 if(not $CheckHeadersOnly_Opt)
1827 {
1828 my $DObjects = parseTag(\$Content, "libs");
1829 if(not $DObjects) {
1830 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1831 }
1832 elsif(lc($DObjects) ne "none")
1833 { # append the descriptor libraries list
1834 if($Descriptor{$LibVersion}{"Libs"})
1835 { # multiple descriptors
1836 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1837 }
1838 else {
1839 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1840 }
1841 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1842 {
1843 if(not -e $Path) {
1844 exitStatus("Access_Error", "can't access \'$Path\'");
1845 }
1846 }
1847 }
1848 }
1849 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1850 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001851 if(not -d $Path) {
1852 exitStatus("Access_Error", "can't access directory \'$Path\'");
1853 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001854 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001855 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001856 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001857 }
1858 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1859 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001860 if(not -d $Path) {
1861 exitStatus("Access_Error", "can't access directory \'$Path\'");
1862 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001863 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001864 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001865 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001866 }
1867 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1868 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001869 if(not -d $Path) {
1870 exitStatus("Access_Error", "can't access directory \'$Path\'");
1871 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001872 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001873 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001874 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001875 $TargetTools{$Path}=1;
1876 }
1877 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1878 $CrossPrefix = $Prefix;
1879 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001880 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001881 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1882 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001883 if(not -d $Path) {
1884 exitStatus("Access_Error", "can't access directory \'$Path\'");
1885 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001886 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001887 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001888 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001889 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001890 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001891 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1892 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001893 if(not -d $Path) {
1894 exitStatus("Access_Error", "can't access directory \'$Path\'");
1895 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001896 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001897 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001898 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001899 }
1900 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001901 { # skip some auto-generated include paths
1902 if(not is_abs($Path))
1903 {
1904 if(my $P = abs_path($Path)) {
1905 $Path = $P;
1906 }
1907 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001908 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001909 }
1910 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001911 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001912 my ($CPath, $Type) = classifyPath($Path);
1913 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001914 }
1915 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001916 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1917 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001918 if($Option!~/\A\-(Wl|l|L)/)
1919 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001920 $CompilerOptions{$LibVersion} .= " ".$Option;
1921 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001922 }
1923 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1924 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1925 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001926 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001927 my ($CPath, $Type) = classifyPath($Path);
1928 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001929 }
1930 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1931 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1932 {
1933 my ($CPath, $Type) = classifyPath($Path);
1934 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1935 }
1936 if(my $DDefines = parseTag(\$Content, "defines"))
1937 {
1938 if($Descriptor{$LibVersion}{"Defines"})
1939 { # multiple descriptors
1940 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1941 }
1942 else {
1943 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1944 }
1945 }
1946 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1947 {
1948 if($Order=~/\A(.+):(.+)\Z/) {
1949 $Include_Order{$LibVersion}{$1} = $2;
1950 }
1951 }
1952 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1953 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001954 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001955 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1956 }
1957 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
1958 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001959 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001960 $SkipSymbols{$LibVersion}{$Symbol} = 1;
1961 }
1962 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
1963 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
1964 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001965 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
1966 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
1967 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001968 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
1969 $SkipConstants{$LibVersion}{$Constant} = 1;
1970 }
1971 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
1972 {
1973 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001974 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001975 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
1976 }
1977 else {
1978 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
1979 }
1980 }
1981}
1982
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001983sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001984{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001985 my $CodeRef = shift(@_);
1986 my $Tag = shift(@_);
1987 if(not $Tag or not $CodeRef) {
1988 return undef;
1989 }
1990 my $Sp = 0;
1991 if(@_) {
1992 $Sp = shift(@_);
1993 }
1994 my $Start = index(${$CodeRef}, "<$Tag>");
1995 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001996 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001997 my $End = index(${$CodeRef}, "</$Tag>");
1998 if($End!=-1)
1999 {
2000 my $TS = length($Tag)+3;
2001 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2002 substr($Content, 0, $TS-1, ""); # cut start tag
2003 substr($Content, -$TS, $TS, ""); # cut end tag
2004 if(not $Sp)
2005 {
2006 $Content=~s/\A\s+//g;
2007 $Content=~s/\s+\Z//g;
2008 }
2009 if(substr($Content, 0, 1) ne "<") {
2010 $Content = xmlSpecChars_R($Content);
2011 }
2012 return $Content;
2013 }
2014 }
2015 return undef;
2016}
2017
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002018sub getInfo($)
2019{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002020 my $DumpPath = $_[0];
2021 return if(not $DumpPath or not -f $DumpPath);
2022
2023 readTUDump($DumpPath);
2024
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002025 # processing info
2026 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002027
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002028 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002029 setAnonTypedef_All();
2030 }
2031
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002032 getTypeInfo_All();
2033 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002034 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002035 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002036 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002037
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002038 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002039 %LibInfo = ();
2040 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002041 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002042 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002043 %TemplateDecl = ();
2044 %StdCxxTypedef = ();
2045 %MissedTypedef = ();
2046 %Typedef_Tr = ();
2047 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002048 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002049
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002050 # clean cache
2051 delete($Cache{"getTypeAttr"});
2052 delete($Cache{"getTypeDeclId"});
2053
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002054 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002055 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002056 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002057 }
2058 else
2059 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002060 if($BinaryOnly and not $ExtendedCheck)
2061 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002062 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002063 }
2064 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002065 remove_Unused($Version, "Extended");
2066 }
2067 }
2068
2069 if($CheckInfo)
2070 {
2071 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2072 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2073 }
2074
2075 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2076 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002077 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002078 }
2079
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002080 if($Debug) {
2081 # debugMangling($Version);
2082 }
2083}
2084
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002085sub readTUDump($)
2086{
2087 my $DumpPath = $_[0];
2088
2089 open(TU_DUMP, $DumpPath);
2090 local $/ = undef;
2091 my $Content = <TU_DUMP>;
2092 close(TU_DUMP);
2093
2094 unlink($DumpPath);
2095
2096 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002097 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002098
2099 # clean memory
2100 undef $Content;
2101
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002102 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002103
2104 foreach (0 .. $#Lines)
2105 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002106 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002107 { # get a number and attributes of a node
2108 next if(not $NodeType{$2});
2109 $LibInfo{$Version}{"info_type"}{$1}=$2;
2110 $LibInfo{$Version}{"info"}{$1}=$3;
2111 }
2112
2113 # clean memory
2114 delete($Lines[$_]);
2115 }
2116
2117 # clean memory
2118 undef @Lines;
2119}
2120
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002121sub simplifyConstants()
2122{
2123 foreach my $Constant (keys(%{$Constants{$Version}}))
2124 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002125 if(defined $Constants{$Version}{$Constant}{"Header"})
2126 {
2127 my $Value = $Constants{$Version}{$Constant}{"Value"};
2128 if(defined $EnumConstants{$Version}{$Value}) {
2129 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2130 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002131 }
2132 }
2133}
2134
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002135sub simplifyNames()
2136{
2137 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2138 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002139 if($Typedef_Eq{$Version}{$Base}) {
2140 next;
2141 }
2142 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2143 if($#Translations==0)
2144 {
2145 if(length($Translations[0])<=length($Base)) {
2146 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2147 }
2148 }
2149 else
2150 { # select most appropriate
2151 foreach my $Tr (@Translations)
2152 {
2153 if($Base=~/\A\Q$Tr\E/)
2154 {
2155 $Typedef_Eq{$Version}{$Base} = $Tr;
2156 last;
2157 }
2158 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002159 }
2160 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002161 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002162 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002163 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002164 if(not $TypeName) {
2165 next;
2166 }
2167 next if(index($TypeName,"<")==-1);# template instances only
2168 if($TypeName=~/>(::\w+)+\Z/)
2169 { # skip unused types
2170 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002171 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002172 foreach my $Base (sort {length($b)<=>length($a)}
2173 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002174 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002175 next if(not $Base);
2176 next if(index($TypeName,$Base)==-1);
2177 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002178 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002179 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002180 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2181 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2182 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002183 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002184 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2185 {
2186 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2187 {
2188 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2189 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002190 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002191 }
2192 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002193 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002194 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002195 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002196 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002197 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2198 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002199 }
2200}
2201
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002202sub setAnonTypedef_All()
2203{
2204 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2205 {
2206 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2207 {
2208 if(isAnon(getNameByInfo($InfoId))) {
2209 $TypedefToAnon{getTypeId($InfoId)} = 1;
2210 }
2211 }
2212 }
2213}
2214
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002215sub setTemplateParams_All()
2216{
2217 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2218 {
2219 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2220 setTemplateParams($_);
2221 }
2222 }
2223}
2224
2225sub setTemplateParams($)
2226{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002227 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002228 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002229 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002230 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002231 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002232 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002233 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002234 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002235 setTemplateInstParams($_[0], $TmplInst_Id);
2236 }
2237 }
2238
2239 $BasicTemplate{$Version}{$Tid} = $_[0];
2240
2241 if(my $Prms = getTreeAttr_Prms($_[0]))
2242 {
2243 if(my $Valu = getTreeAttr_Valu($Prms))
2244 {
2245 my $Vector = getTreeVec($Valu);
2246 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2247 {
2248 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2249 {
2250 if(my $Name = getNameByInfo($Val))
2251 {
2252 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2253 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2254 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2255 }
2256 else {
2257 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2258 }
2259 }
2260 }
2261 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002263 }
2264 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002265 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002266 {
2267 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2268 {
2269 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002270 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002271 }
2272 }
2273 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002274}
2275
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002276sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002277{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002278 my ($Tmpl, $Inst) = @_;
2279
2280 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002281 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002282 my ($Params_InfoId, $ElemId) = ();
2283 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2284 $Params_InfoId = $1;
2285 }
2286 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2287 $ElemId = $1;
2288 }
2289 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002290 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002291 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2292 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2293 {
2294 my ($PPos, $PTypeId) = ($1, $2);
2295 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2296 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002297 if($PType eq "template_type_parm") {
2298 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002299 }
2300 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002301 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2302 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002303 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002304 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002305 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002306 else
2307 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002308 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002309 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002311 }
2312 }
2313 }
2314}
2315
2316sub getTypeDeclId($)
2317{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002318 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002319 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002320 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2321 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2322 }
2323 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2324 {
2325 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2326 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2327 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002328 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002329 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002330 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002331}
2332
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002333sub getTypeInfo_All()
2334{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002335 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002336 { # support for GCC < 4.5
2337 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2338 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2339 # FIXME: check GCC versions
2340 addMissedTypes_Pre();
2341 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002342
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002343 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002344 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002345 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2346 if($IType=~/_type\Z/ and $IType ne "function_type"
2347 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002348 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002349 }
2350 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002351
2352 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002353 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002354 "Name" => "...",
2355 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002356 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002357 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002358 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002359
2360 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002361 { # support for GCC < 4.5
2362 addMissedTypes_Post();
2363 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002364
2365 if($ADD_TMPL_INSTANCES)
2366 {
2367 # templates
2368 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2369 {
2370 if(defined $TemplateMap{$Version}{$Tid}
2371 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2372 {
2373 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2374 {
2375 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2376 {
2377 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2378 {
2379 if(my %MAttr = getTypeAttr($MembTypeId))
2380 {
2381 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2382 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2383 }
2384 }
2385 }
2386 }
2387 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2388 {
2389 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2390 {
2391 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2392
2393 if($NBid ne $Bid)
2394 {
2395 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2396 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2397 }
2398 }
2399 }
2400 }
2401 }
2402 }
2403}
2404
2405sub createType($$)
2406{
2407 my ($Attr, $LibVersion) = @_;
2408 my $NewId = ++$MAX_ID;
2409
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002410 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002411 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002412 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002413
2414 return "$NewId";
2415}
2416
2417sub instType($$$)
2418{ # create template instances
2419 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002420
2421 if(not $TypeInfo{$LibVersion}{$Tid}) {
2422 return undef;
2423 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002424 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2425
2426 foreach my $Key (sort keys(%{$Map}))
2427 {
2428 if(my $Val = $Map->{$Key})
2429 {
2430 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2431
2432 if(defined $Attr->{"NameSpace"}) {
2433 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2434 }
2435 foreach (keys(%{$Attr->{"TParam"}})) {
2436 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2437 }
2438 }
2439 else
2440 { # remove absent
2441 # _Traits, etc.
2442 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002443 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002444 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2445 }
2446 foreach (keys(%{$Attr->{"TParam"}}))
2447 {
2448 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2449 delete($Attr->{"TParam"}{$_});
2450 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002451 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002452 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2453 }
2454 }
2455 }
2456 }
2457
2458 my $Tmpl = 0;
2459
2460 if(defined $Attr->{"TParam"})
2461 {
2462 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2463 {
2464 my $PName = $Attr->{"TParam"}{$_}{"name"};
2465
2466 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2467 {
2468 my %Base = get_BaseType($PTid, $LibVersion);
2469
2470 if($Base{"Type"} eq "TemplateParam"
2471 or defined $Base{"Template"})
2472 {
2473 $Tmpl = 1;
2474 last
2475 }
2476 }
2477 }
2478 }
2479
2480 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2481 return "$Id";
2482 }
2483 else
2484 {
2485 if(not $Tmpl) {
2486 delete($Attr->{"Template"});
2487 }
2488
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002489 my $New = createType($Attr, $LibVersion);
2490
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002491 my %EMap = ();
2492 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2493 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2494 }
2495 foreach (keys(%{$Map})) {
2496 $EMap{$_} = $Map->{$_};
2497 }
2498
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002499 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2500 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002501 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002502 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002503 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002504 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002505 {
2506 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2507
2508 if($NBid ne $Bid)
2509 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002510 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2511 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002512 }
2513 }
2514 }
2515
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002516 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002517 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002518 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2519 {
2520 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2521 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2522 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002523 }
2524 }
2525
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002526 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002527 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002528 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2529 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002530 }
2531 }
2532
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002533 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2534 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002535 }
2536
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002537 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002538 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002539}
2540
2541sub addMissedTypes_Pre()
2542{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002543 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002544 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2545 { # detecting missed typedefs
2546 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2547 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002548 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002549 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002550 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002551 if($TypeType eq "Unknown")
2552 { # template_type_parm
2553 next;
2554 }
2555 my $TypeDeclId = getTypeDeclId($TypeId);
2556 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2557 my $TypedefName = getNameByInfo($MissedTDid);
2558 next if(not $TypedefName);
2559 next if($TypedefName eq "__float80");
2560 next if(isAnon($TypedefName));
2561 if(not $TypeDeclId
2562 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002563 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002564 }
2565 }
2566 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002567 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002568 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002569 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002570 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002571 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002572 next;
2573 }
2574 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002575 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002576 if(not $TypedefName) {
2577 next;
2578 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002579 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002580 my %MissedInfo = ( # typedef info
2581 "Name" => $TypedefName,
2582 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002583 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002584 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002585 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002586 my ($H, $L) = getLocation($MissedTDid);
2587 $MissedInfo{"Header"} = $H;
2588 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002589 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002590 { # other types
2591 next;
2592 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002593 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002594 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002595 next;
2596 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002597 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002598 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002599 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002600 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002601 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002602 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002603 next;
2604 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002605 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002606 next;
2607 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002608 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002609 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002610 next;
2611 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002612 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002613 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002614 next;
2615 }
2616 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002617
2618 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2619
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002620 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002621 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002622 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002623 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002624 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002625
2626 # add missed & remove other
2627 $TypeInfo{$Version} = \%AddTypes;
2628 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002629}
2630
2631sub addMissedTypes_Post()
2632{
2633 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2634 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002635 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2636 {
2637 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2638 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2639 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2640 }
2641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002642 }
2643}
2644
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002645sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002646{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002647 my $TypeId = $_[0];
2648 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2649 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002650 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002651 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002652 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002653}
2654
2655sub getArraySize($$)
2656{
2657 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002658 if(my $Size = getSize($TypeId))
2659 {
2660 my $Elems = $Size/$BYTE_SIZE;
2661 while($BaseName=~s/\s*\[(\d+)\]//) {
2662 $Elems/=$1;
2663 }
2664 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2665 {
2666 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2667 $Elems/=$BasicSize;
2668 }
2669 }
2670 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002671 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002672 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002673}
2674
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002675sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002676{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002677 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002678 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002679 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2680 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002681 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002682 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2683 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2684 if(not $NodeType)
2685 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002686 return ();
2687 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002688 if($NodeType eq "tree_vec")
2689 {
2690 if($Pos!=$#Positions)
2691 { # select last vector of parameters ( ns<P1>::type<P2> )
2692 next;
2693 }
2694 }
2695 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2696 foreach my $P (@Params)
2697 {
2698 if($P eq "") {
2699 return ();
2700 }
2701 elsif($P ne "\@skip\@") {
2702 @TmplParams = (@TmplParams, $P);
2703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002704 }
2705 }
2706 return @TmplParams;
2707}
2708
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002709sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002710{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002711 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002712 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002713 if(defined $TypeInfo{$Version}{$TypeId}
2714 and $TypeInfo{$Version}{$TypeId}{"Name"})
2715 { # already created
2716 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002717 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002718 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2719 { # incomplete type
2720 return ();
2721 }
2722 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2723
2724 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002725 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002726
2727 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2728 {
2729 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2730 {
2731 if($Info=~/qual[ ]*:/)
2732 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002733 my $NewId = ++$MAX_ID;
2734
2735 $MissedBase{$Version}{$TypeId} = "$NewId";
2736 $MissedBase_R{$Version}{$NewId} = $TypeId;
2737 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2738 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002739 }
2740 }
2741 $TypeAttr{"Type"} = "Typedef";
2742 }
2743 else {
2744 $TypeAttr{"Type"} = getTypeType($TypeId);
2745 }
2746
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002747 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2748 {
2749 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2750 { # local code
2751 return ();
2752 }
2753 }
2754
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002755 if($TypeAttr{"Type"} eq "Unknown") {
2756 return ();
2757 }
2758 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2759 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002760 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002761 if(my $TName = $TypeAttr{"Name"})
2762 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002763 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002764 $TName_Tid{$Version}{$TName} = $TypeId;
2765 return %TypeAttr;
2766 }
2767 else {
2768 return ();
2769 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002770 }
2771 elsif($TypeAttr{"Type"} eq "Array")
2772 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002773 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2774 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002775 return ();
2776 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002777 if(my $Algn = getAlgn($TypeId)) {
2778 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2779 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002780 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002781 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002782 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002783 if(not $BTAttr{"Name"}) {
2784 return ();
2785 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002786 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002787 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002788 if(my $Size = getSize($TypeId)) {
2789 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2790 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002791 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002792 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2793 }
2794 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002795 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002796 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002797 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002798 else
2799 {
2800 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002801 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002802 $TypeAttr{"Name"} = $1."[]".$2;
2803 }
2804 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002805 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002806 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002807 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002808 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002809 if($BTAttr{"Header"}) {
2810 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002811 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002812 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002813 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2814 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002815 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002816 return ();
2817 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002818 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002819 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002820 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002821 if($TypeAttr{"Name"})
2822 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002823 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002824
2825 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2826 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002827 { # NOTE: register only one int: with built-in decl
2828 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2829 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2830 }
2831 }
2832 return %TypeAttr;
2833 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002834 else {
2835 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002836 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002837 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002838 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2839 {
2840 %TypeAttr = getTrivialTypeAttr($TypeId);
2841 if($TypeAttr{"Name"})
2842 {
2843 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2844 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2845 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2846 }
2847 return %TypeAttr;
2848 }
2849 else {
2850 return ();
2851 }
2852 }
2853 elsif($TypeAttr{"Type"} eq "SizeOf")
2854 {
2855 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2856 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2857 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2858 if($TypeAttr{"Name"})
2859 {
2860 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2861 return %TypeAttr;
2862 }
2863 else {
2864 return ();
2865 }
2866 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002867 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002868 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002869 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2870 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002871 return ();
2872 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002873 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002874 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002875 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002876 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002877 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002878 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002879 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002881 }
2882 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002883 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002884 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002885 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002886 return ();
2887 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002888 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002889 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002890 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002891 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002892 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002893 }
2894 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002895 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002896 {
2897 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002898 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002899 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002900 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002901 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2902 }
2903 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002904 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002905 }
2906 }
2907 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002908 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002909 }
2910 if($TypeAttr{"Type"} eq "Typedef")
2911 {
2912 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002913
2914 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2915 return ();
2916 }
2917
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002918 if(isAnon($TypeAttr{"Name"}))
2919 { # anon typedef to anon type: ._N
2920 return ();
2921 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002922
2923 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2924 { # artificial typedef of "struct X" to "X"
2925 $TypeAttr{"Artificial"} = 1;
2926 }
2927
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002928 if(my $NS = getNameSpace($TypeDeclId))
2929 {
2930 my $TypeName = $TypeAttr{"Name"};
2931 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2932 { # "some_type" is the typedef to "struct some_type" in C++
2933 if($3) {
2934 $TypeAttr{"Name"} = $3."::".$TypeName;
2935 }
2936 }
2937 else
2938 {
2939 $TypeAttr{"NameSpace"} = $NS;
2940 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002941
2942 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2943 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2944 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002945 if($BTAttr{"NameSpace"}
2946 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002947 { # types like "std::fpos<__mbstate_t>" are
2948 # not covered by typedefs in the TU dump
2949 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002950 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2951 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002952 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002953 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002954 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002955 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002956 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002957 }
2958 }
2959 }
2960 }
2961 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002962 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002963 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002964 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002965 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2966 { # typedef int*const TYPEDEF; // first
2967 # int foo(TYPEDEF p); // const is optimized out
2968 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2969 if($BTAttr{"Name"}=~/</)
2970 {
2971 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2972 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2973 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002974 }
2975 }
2976 }
2977 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
2978 }
2979 if(not $TypeAttr{"Size"})
2980 {
2981 if($TypeAttr{"Type"} eq "Pointer") {
2982 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
2983 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002984 elsif($BTAttr{"Size"}) {
2985 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002986 }
2987 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002988 if(my $Algn = getAlgn($TypeId)) {
2989 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2990 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002991 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002992 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
2993 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002994 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002995 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002996 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002997 { # typedef to "class Class"
2998 # should not be registered in TName_Tid
2999 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3000 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003002 }
3003 return %TypeAttr;
3004 }
3005}
3006
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003007sub getTreeVec($)
3008{
3009 my %Vector = ();
3010 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3011 {
3012 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3013 { # string length is N-1 because of the null terminator
3014 $Vector{$1} = $2;
3015 }
3016 }
3017 return \%Vector;
3018}
3019
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003020sub get_TemplateParam($$)
3021{
3022 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003023 return () if(not $Type_Id);
3024 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3025 return () if(not $NodeType);
3026 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003027 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003028 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003029 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003030 my $Num = getNodeIntCst($Type_Id);
3031 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003032 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003033 }
3034 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003035 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003036 }
3037 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003038 elsif($NodeType eq "string_cst") {
3039 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003040 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003041 elsif($NodeType eq "tree_vec")
3042 {
3043 my $Vector = getTreeVec($Type_Id);
3044 my @Params = ();
3045 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3046 {
3047 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3048 push(@Params, $P2);
3049 }
3050 }
3051 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003052 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003053 elsif($NodeType eq "parm_decl")
3054 {
3055 (getNameByInfo($Type_Id));
3056 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003057 else
3058 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003059 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003060 my $PName = $ParamAttr{"Name"};
3061 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003062 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003063 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003064 if($PName=~/\>/)
3065 {
3066 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003067 $PName = $Cover;
3068 }
3069 }
3070 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003071 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003072 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3073 # template<typename _Key, typename _Compare = std::less<_Key>
3074 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3075 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3076 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3077 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003078 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003079 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003080 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003081 }
3082}
3083
3084sub cover_stdcxx_typedef($)
3085{
3086 my $TypeName = $_[0];
3087 if(my @Covers = sort {length($a)<=>length($b)}
3088 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3089 { # take the shortest typedef
3090 # FIXME: there may be more than
3091 # one typedefs to the same type
3092 return $Covers[0];
3093 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003094 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003095 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3096 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3097 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003098 if(my $Cover = $Covers[0])
3099 {
3100 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3101 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003103 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003104 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003105}
3106
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003107sub getNodeIntCst($)
3108{
3109 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003110 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003111 if($EnumMembName_Id{$Version}{$CstId}) {
3112 return $EnumMembName_Id{$Version}{$CstId};
3113 }
3114 elsif((my $Value = getTreeValue($CstId)) ne "")
3115 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003116 if($Value eq "0")
3117 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003118 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003119 return "false";
3120 }
3121 else {
3122 return "0";
3123 }
3124 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003125 elsif($Value eq "1")
3126 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003127 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003128 return "true";
3129 }
3130 else {
3131 return "1";
3132 }
3133 }
3134 else {
3135 return $Value;
3136 }
3137 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003138 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003139}
3140
3141sub getNodeStrCst($)
3142{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003143 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3144 {
3145 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003146 {
3147 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3148 { # string length is N-1 because of the null terminator
3149 return substr($1, 0, $2-1);
3150 }
3151 else
3152 { # identifier_node
3153 return substr($1, 0, $2);
3154 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003156 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003157 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003158}
3159
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003160sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003161{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003162 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003163 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3164 if($Type eq "FieldPtr") {
3165 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3166 }
3167 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3168 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003169 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003170 if($Type eq "MethodPtr")
3171 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003172 if(my $Size = getSize($TypeId))
3173 {
3174 $Size/=$BYTE_SIZE;
3175 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003176 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003177 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003178 if(my $Algn = getAlgn($TypeId)) {
3179 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003181 # Return
3182 if($Type eq "FieldPtr")
3183 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003184 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003185 if($ReturnAttr{"Name"}) {
3186 $MemPtrName .= $ReturnAttr{"Name"};
3187 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003188 $TypeAttr{"Return"} = $PtrId;
3189 }
3190 else
3191 {
3192 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3193 {
3194 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003195 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3196 if(not $ReturnAttr{"Name"})
3197 { # templates
3198 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003199 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003200 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003201 $TypeAttr{"Return"} = $ReturnTypeId;
3202 }
3203 }
3204 # Class
3205 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3206 {
3207 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003208 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003209 if($Class{"Name"}) {
3210 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3211 }
3212 else {
3213 $MemPtrName .= " (*)";
3214 }
3215 }
3216 else {
3217 $MemPtrName .= " (*)";
3218 }
3219 # Parameters
3220 if($Type eq "FuncPtr"
3221 or $Type eq "MethodPtr")
3222 {
3223 my @ParamTypeName = ();
3224 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3225 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003226 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003227 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003228 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003229 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003230 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3231 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003232 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003233 my $PTypeId = $1;
3234 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003235 if(not $ParamAttr{"Name"})
3236 { # templates (template_type_parm), etc.
3237 return ();
3238 }
3239 if($ParamAttr{"Name"} eq "void") {
3240 last;
3241 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003242 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003243 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003244 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003245 push(@ParamTypeName, $ParamAttr{"Name"});
3246 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003247 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3248 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003249 }
3250 else {
3251 last;
3252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003253 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003254 else {
3255 last;
3256 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003257 }
3258 }
3259 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3260 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003261 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003262 return %TypeAttr;
3263}
3264
3265sub getTreeTypeName($)
3266{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003267 my $TypeId = $_[0];
3268 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003269 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003270 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003271 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003272 if(my $Name = getNameByInfo($TypeId))
3273 { # bit_size_type
3274 return $Name;
3275 }
3276 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003277 return "unsigned int";
3278 }
3279 else {
3280 return "int";
3281 }
3282 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003283 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003284 return getNameByInfo($1);
3285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003286 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003287 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003288}
3289
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003290sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003291{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003292 my $Ptd = pointTo($_[0]);
3293 return 0 if(not $Ptd);
3294 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003295 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003296 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3297 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003298 }
3299 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003300 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3301 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003302 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003303 if($InfoT1 eq "pointer_type"
3304 and $InfoT2 eq "function_type") {
3305 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003306 }
3307 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003308 return 0;
3309}
3310
3311sub isMethodPtr($)
3312{
3313 my $Ptd = pointTo($_[0]);
3314 return 0 if(not $Ptd);
3315 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3316 {
3317 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3318 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3319 and $Info=~/ ptrmem /) {
3320 return 1;
3321 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003322 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003323 return 0;
3324}
3325
3326sub isFieldPtr($)
3327{
3328 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3329 {
3330 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3331 and $Info=~/ ptrmem /) {
3332 return 1;
3333 }
3334 }
3335 return 0;
3336}
3337
3338sub pointTo($)
3339{
3340 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3341 {
3342 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3343 return $1;
3344 }
3345 }
3346 return "";
3347}
3348
3349sub getTypeTypeByTypeId($)
3350{
3351 my $TypeId = $_[0];
3352 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3353 {
3354 my $NType = $NodeType{$TType};
3355 if($NType eq "Intrinsic") {
3356 return $NType;
3357 }
3358 elsif(isFuncPtr($TypeId)) {
3359 return "FuncPtr";
3360 }
3361 elsif(isMethodPtr($TypeId)) {
3362 return "MethodPtr";
3363 }
3364 elsif(isFieldPtr($TypeId)) {
3365 return "FieldPtr";
3366 }
3367 elsif($NType ne "Other") {
3368 return $NType;
3369 }
3370 }
3371 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003372}
3373
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003374my %UnQual = (
3375 "r"=>"restrict",
3376 "v"=>"volatile",
3377 "c"=>"const",
3378 "cv"=>"const volatile"
3379);
3380
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003381sub getQual($)
3382{
3383 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003384 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3385 {
3386 my ($Qual, $To) = ();
3387 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3388 $Qual = $UnQual{$1};
3389 }
3390 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3391 $To = $1;
3392 }
3393 if($Qual and $To) {
3394 return ($Qual, $To);
3395 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003396 }
3397 return ();
3398}
3399
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003400sub getQualType($)
3401{
3402 if($_[0] eq "const volatile") {
3403 return "ConstVolatile";
3404 }
3405 return ucfirst($_[0]);
3406}
3407
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003408sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003409{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003410 my $TypeId = $_[0];
3411 my $TypeDeclId = getTypeDeclId($TypeId);
3412 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003413 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003414 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3415 return "Typedef";
3416 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003417 }
3418 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3419 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003420 if(($Qual or $To) and $TypeDeclId
3421 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003422 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003423 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003424 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003425 elsif(not $MissedBase_R{$Version}{$TypeId}
3426 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003427 return "Typedef";
3428 }
3429 elsif($Qual)
3430 { # qualified types
3431 return getQualType($Qual);
3432 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003433
3434 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3435 { # typedef struct { ... } name
3436 $TypeTypedef{$Version}{$TypeId} = $1;
3437 }
3438
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003439 my $TypeType = getTypeTypeByTypeId($TypeId);
3440 if($TypeType eq "Struct")
3441 {
3442 if($TypeDeclId
3443 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3444 return "Template";
3445 }
3446 }
3447 return $TypeType;
3448}
3449
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003450sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003451{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003452 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003453 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003454 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3455 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3456 return 0;
3457 }
3458 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3459 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003460 if(my $TDid = getTypeDeclId($_[0]))
3461 {
3462 if(getTypeId($TDid) eq $_[0]
3463 and getNameByInfo($TDid))
3464 {
3465 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3466 return $1;
3467 }
3468 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003469 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003470 }
3471 }
3472 return 0;
3473}
3474
3475sub selectBaseType($)
3476{
3477 my $TypeId = $_[0];
3478 if(defined $MissedTypedef{$Version}{$TypeId})
3479 { # add missed typedefs
3480 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3481 return ($TypeId, "");
3482 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003483 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003484 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3485 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003486
3487 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3488 my $MB = $MissedBase{$Version}{$TypeId};
3489
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003490 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003491 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003492 and (getTypeId($1) ne $TypeId)
3493 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003494 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003495 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003496 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003497 elsif($MB)
3498 { # add base
3499 return ($MB, "");
3500 }
3501 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003502 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003503 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003504 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003505 elsif($Qual or $To)
3506 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003507 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003508 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003509 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003510 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003511 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003512 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003513 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003514 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003515 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003516 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003517 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003518 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003519 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003520 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003521 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003522 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003523 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003524 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003525 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003526 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003527
3528 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003529}
3530
3531sub getSymbolInfo_All()
3532{
3533 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3534 { # reverse order
3535 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003536 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003537 }
3538 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003539
3540 if($ADD_TMPL_INSTANCES)
3541 {
3542 # templates
3543 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3544 {
3545 my %Map = ();
3546
3547 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3548 {
3549 if(defined $TemplateMap{$Version}{$ClassId})
3550 {
3551 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3552 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3553 }
3554 }
3555 }
3556
3557 if(defined $TemplateMap{$Version}{$Sid})
3558 {
3559 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3560 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3561 }
3562 }
3563
3564 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3565 {
3566 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3567 {
3568 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3569 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3570 }
3571 }
3572 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3573 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3574 }
3575 }
3576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003577}
3578
3579sub getVarInfo_All()
3580{
3581 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3582 { # reverse order
3583 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003584 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003585 }
3586 }
3587}
3588
3589sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003590 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003591}
3592
3593sub getVarInfo($)
3594{
3595 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003596 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003597 {
3598 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3599 if($NSInfoType and $NSInfoType eq "function_decl") {
3600 return;
3601 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003602 }
3603 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3604 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3605 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3606 delete($SymbolInfo{$Version}{$InfoId});
3607 return;
3608 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003609 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003610 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003611 delete($SymbolInfo{$Version}{$InfoId});
3612 return;
3613 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003614 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3615 delete($SymbolInfo{$Version}{$InfoId});
3616 return;
3617 }
3618 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003619 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3620 {
3621 if($OSgroup eq "windows")
3622 { # cut the offset
3623 $MnglName=~s/\@\d+\Z//g;
3624 }
3625 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3626 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003627 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003628 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003629 { # validate mangled name
3630 delete($SymbolInfo{$Version}{$InfoId});
3631 return;
3632 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003633 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003634 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003635 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003636 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003637 }
3638 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3639 { # non-public global data
3640 delete($SymbolInfo{$Version}{$InfoId});
3641 return;
3642 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003643 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003644 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003645 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003646 if(not defined $TypeInfo{$Version}{$Rid}
3647 or not $TypeInfo{$Version}{$Rid}{"Name"})
3648 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003649 delete($SymbolInfo{$Version}{$InfoId});
3650 return;
3651 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003652 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3653 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003654 if(defined $Val) {
3655 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3656 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003657 }
3658 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003659 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3660 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003661 if(not defined $TypeInfo{$Version}{$ClassId}
3662 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3663 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003664 delete($SymbolInfo{$Version}{$InfoId});
3665 return;
3666 }
3667 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003668 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3669 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003670 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003671 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003672 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003673 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003674 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003675 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003676 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003677 if(not $CheckHeadersOnly)
3678 {
3679 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3680 {
3681 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3682 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3683 {
3684 if(link_symbol($ShortName, $Version, "-Deps"))
3685 { # "const" global data is mangled as _ZL... in the TU dump
3686 # but not mangled when compiling a C shared library
3687 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3688 }
3689 }
3690 }
3691 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003692 if($COMMON_LANGUAGE{$Version} eq "C++")
3693 {
3694 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3695 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003696 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003697 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3698 }
3699 }
3700 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3701 { # try to mangle symbol (link with libraries)
3702 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3703 }
3704 if($OStarget eq "windows")
3705 {
3706 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3707 { # link MS C++ symbols from library with GCC symbols from headers
3708 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3709 }
3710 }
3711 }
3712 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3713 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3714 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003715 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3716 {
3717 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3718 { # non-target symbols
3719 delete($SymbolInfo{$Version}{$InfoId});
3720 return;
3721 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003722 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003723 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3724 {
3725 if(defined $MissedTypedef{$Version}{$Rid})
3726 {
3727 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3728 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3729 }
3730 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003731 }
3732 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003733 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003734 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3735 }
3736 if($ShortName=~/\A(_Z|\?)/) {
3737 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3738 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003739
3740 if($ExtraDump) {
3741 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3742 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003743}
3744
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003745sub isConstType($$)
3746{
3747 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003748 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003749 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003750 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003751 }
3752 return ($Base{"Type"} eq "Const");
3753}
3754
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003755sub getTrivialName($$)
3756{
3757 my ($TypeInfoId, $TypeId) = @_;
3758 my %TypeAttr = ();
3759 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3760 if(not $TypeAttr{"Name"}) {
3761 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3762 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003763 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003764 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003765 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003766 if(isAnon($TypeAttr{"Name"}))
3767 {
3768 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003769 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003770 { # searching for a first not anon scope
3771 if($NSId eq $NameSpaceId) {
3772 last;
3773 }
3774 else
3775 {
3776 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3777 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003778 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003779 last;
3780 }
3781 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003782 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003783 }
3784 }
3785 else
3786 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003787 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003788 {
3789 if($NameSpaceId ne $TypeId) {
3790 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3791 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003792 }
3793 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003794 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003795 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3796 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003797 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003798 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003799 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003800 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003801 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003802 if($TypeAttr{"NameSpace"}) {
3803 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3804 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003805 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003806 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3807 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003808 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003809 if(my @TParams = getTParams($TypeId, "Type")) {
3810 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3811 }
3812 else {
3813 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3814 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003815 }
3816 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3817}
3818
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003819sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003820{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003821 my $TypeId = $_[0];
3822 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003823
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003824 my %TypeAttr = ();
3825
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003826 if($TemplateDecl{$Version}{$TypeId})
3827 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003828 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003829 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003830
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003831 setTypeAccess($TypeId, \%TypeAttr);
3832 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3833 if(isBuiltIn($TypeAttr{"Header"}))
3834 {
3835 delete($TypeAttr{"Header"});
3836 delete($TypeAttr{"Line"});
3837 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003838
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003839 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003840 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3841 if(not $TypeAttr{"Name"}) {
3842 return ();
3843 }
3844 if(not $TypeAttr{"NameSpace"}) {
3845 delete($TypeAttr{"NameSpace"});
3846 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003847
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003848 if($TypeAttr{"Type"} eq "Intrinsic")
3849 {
3850 if(defined $TypeAttr{"Header"})
3851 {
3852 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3853 { # support for SUSE 11.2
3854 # integer_type has srcp dump{1-2}.i
3855 delete($TypeAttr{"Header"});
3856 }
3857 }
3858 }
3859
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003860 my $Tmpl = undef;
3861
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003862 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003863 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003864 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3865
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003866 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003867 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003868 foreach my $Pos (0 .. $#TParams)
3869 {
3870 my $Val = $TParams[$Pos];
3871 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3872
3873 if(not defined $TypeAttr{"Template"})
3874 {
3875 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3876
3877 if($Base{"Type"} eq "TemplateParam"
3878 or defined $Base{"Template"}) {
3879 $TypeAttr{"Template"} = 1;
3880 }
3881 }
3882
3883 if($Tmpl)
3884 {
3885 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3886 {
3887 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3888
3889 if($Val eq $Arg) {
3890 $TypeAttr{"Template"} = 1;
3891 }
3892 }
3893 }
3894 }
3895
3896 if($Tmpl)
3897 {
3898 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3899 {
3900 if($Pos>$#TParams)
3901 {
3902 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3903 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3904 }
3905 }
3906 }
3907 }
3908
3909 if($ADD_TMPL_INSTANCES)
3910 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003911 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003912 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003913 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003914 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003915 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003916 {
3917 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3918 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3919 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003920 }
3921 if(not getTreeAttr_Binf($TypeId))
3922 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003923 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3924 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3925 }
3926 }
3927 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003928 }
3929 }
3930 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003931
3932 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3933
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003934 if(my $Size = getSize($TypeId))
3935 {
3936 $Size = $Size/$BYTE_SIZE;
3937 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003938 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003939 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003940 {
3941 if($ExtraDump)
3942 {
3943 if(not defined $TypeAttr{"Memb"}
3944 and not $Tmpl)
3945 { # declaration only
3946 $TypeAttr{"Forward"} = 1;
3947 }
3948 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003949 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003950
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003951 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003952 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003953 {
3954 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003955 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003956 }
3957 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003958 or $TypeAttr{"Type"} eq "Class")
3959 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003960 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003961 if($Skip) {
3962 return ();
3963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003964 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003965 if(my $Algn = getAlgn($TypeId)) {
3966 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3967 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003968 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003969
3970 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3971 {
3972 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003973 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003974 {
3975 if(not isAnon($TypeAttr{"Name"})) {
3976 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
3977 }
3978 }
3979 }
3980
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003981 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003982 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
3983 {
3984 my @Entries = split(/\n/, $VTable);
3985 foreach (1 .. $#Entries)
3986 {
3987 my $Entry = $Entries[$_];
3988 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003989 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003990 }
3991 }
3992 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003993
3994 if($TypeAttr{"Type"} eq "Enum")
3995 {
3996 if(not $TypeAttr{"NameSpace"})
3997 {
3998 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
3999 {
4000 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004001 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004002 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004003 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004004 "Header"=>$TypeAttr{"Header"}
4005 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004006 if(isAnon($TypeAttr{"Name"}))
4007 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004008 if($ExtraDump
4009 or is_target_header($TypeAttr{"Header"}, $Version))
4010 {
4011 %{$Constants{$Version}{$MName}} = (
4012 "Value" => $MVal,
4013 "Header" => $TypeAttr{"Header"}
4014 );
4015 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004016 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004017 }
4018 }
4019 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004020 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004021 {
4022 if(defined $TypedefToAnon{$TypeId}) {
4023 $TypeAttr{"AnonTypedef"} = 1;
4024 }
4025 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004026
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004027 return %TypeAttr;
4028}
4029
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004030sub simplifyVTable($)
4031{
4032 my $Content = $_[0];
4033 if($Content=~s/ \[with (.+)]//)
4034 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4035 if(my @Elems = separate_Params($1, 0, 0))
4036 {
4037 foreach my $Elem (@Elems)
4038 {
4039 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4040 {
4041 my ($Arg, $Val) = ($1, $2);
4042
4043 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4044 $Content=~s/,\s*$Arg\b//g;
4045 }
4046 else {
4047 $Content=~s/\b$Arg\b/$Val/g;
4048 }
4049 }
4050 }
4051 }
4052 }
4053
4054 return $Content;
4055}
4056
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004057sub detect_lang($)
4058{
4059 my $TypeId = $_[0];
4060 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004061 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004062 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004063 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4064 }
4065 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004066 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004067 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004068 while($Fncs)
4069 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004070 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004071 return 1;
4072 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004073 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004074 }
4075 }
4076 return 0;
4077}
4078
4079sub setSpec($$)
4080{
4081 my ($TypeId, $TypeAttr) = @_;
4082 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4083 if($Info=~/\s+spec\s+/) {
4084 $TypeAttr->{"Spec"} = 1;
4085 }
4086}
4087
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004088sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004089{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004090 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004091 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004092 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004093 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004094 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004095 my $Pos = 0;
4096 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4097 {
4098 my ($Access, $BInfoId) = ($1, $2);
4099 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004100
4101 if($ClassId==$TypeId)
4102 { # class A<N>:public A<N-1>
4103 next;
4104 }
4105
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004106 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4107 if(not $CType or $CType eq "template_type_parm"
4108 or $CType eq "typename_type")
4109 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004110 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004111 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004112 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004113 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004114 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4115 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004116 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004117 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4118 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004119 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004120 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004121 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004122 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4123 }
4124 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004125 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004126 }
4127 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004128 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004129}
4130
4131sub getBinfClassId($)
4132{
4133 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4134 $Info=~/type[ ]*:[ ]*@(\d+) /;
4135 return $1;
4136}
4137
4138sub unmangledFormat($$)
4139{
4140 my ($Name, $LibVersion) = @_;
4141 $Name = uncover_typedefs($Name, $LibVersion);
4142 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4143 $Name=~s/\(\w+\)(\d)/$1/;
4144 return $Name;
4145}
4146
4147sub modelUnmangled($$)
4148{
4149 my ($InfoId, $Compiler) = @_;
4150 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4151 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4152 }
4153 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4154 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4155 $PureSignature = "~".$PureSignature;
4156 }
4157 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4158 {
4159 my (@Params, @ParamTypes) = ();
4160 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4161 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4162 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4163 }
4164 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4165 { # checking parameters
4166 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004167 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004168 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004169 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004170
4171 if($PName eq "this"
4172 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4173 {
4174 next;
4175 }
4176
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004177 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004178 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004179 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004180 }
4181 @ParamTypes = (@ParamTypes, $PTName);
4182 }
4183 if(@ParamTypes) {
4184 $PureSignature .= "(".join(", ", @ParamTypes).")";
4185 }
4186 else
4187 {
4188 if($Compiler eq "MSVC")
4189 {
4190 $PureSignature .= "(void)";
4191 }
4192 else
4193 { # GCC
4194 $PureSignature .= "()";
4195 }
4196 }
4197 $PureSignature = delete_keywords($PureSignature);
4198 }
4199 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4200 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004201 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004202 $PureSignature = $ClassName."::".$PureSignature;
4203 }
4204 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4205 $PureSignature = $NS."::".$PureSignature;
4206 }
4207 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4208 $PureSignature .= " const";
4209 }
4210 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4211 $PureSignature .= " volatile";
4212 }
4213 my $ShowReturn = 0;
4214 if($Compiler eq "MSVC"
4215 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4216 {
4217 $ShowReturn=1;
4218 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004219 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4220 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004221 {
4222 $ShowReturn=1;
4223 }
4224 if($ShowReturn)
4225 { # mangled names for template function specializations include return value
4226 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4227 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004228 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004229 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4230 $PureSignature = $ReturnName." ".$PureSignature;
4231 }
4232 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004233 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004234}
4235
4236sub mangle_symbol($$$)
4237{ # mangling for simple methods
4238 # see gcc-4.6.0/gcc/cp/mangle.c
4239 my ($InfoId, $LibVersion, $Compiler) = @_;
4240 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4241 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4242 }
4243 my $Mangled = "";
4244 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004245 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004246 }
4247 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004248 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004249 }
4250 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4251}
4252
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004253sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004254{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004255 my ($InfoId, $LibVersion) = @_;
4256 return "";
4257}
4258
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004259sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004260{ # see gcc-4.6.0/gcc/cp/mangle.c
4261 my ($InfoId, $LibVersion) = @_;
4262 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004263 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004264 my %Repl = ();# SN_ replacements
4265 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4266 {
4267 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4268 if($MangledClass!~/\AN/) {
4269 $MangledClass = "N".$MangledClass;
4270 }
4271 else {
4272 $MangledClass=~s/E\Z//;
4273 }
4274 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4275 $MangledClass=~s/\AN/NV/;
4276 }
4277 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4278 $MangledClass=~s/\AN/NK/;
4279 }
4280 $Mangled .= $MangledClass;
4281 }
4282 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4283 { # mangled by name due to the absence of structured info
4284 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4285 if($MangledNS!~/\AN/) {
4286 $MangledNS = "N".$MangledNS;
4287 }
4288 else {
4289 $MangledNS=~s/E\Z//;
4290 }
4291 $Mangled .= $MangledNS;
4292 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004293 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004294 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004295 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004296 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004297 foreach (@TPos) {
4298 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4299 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004300 }
4301 elsif($TmplParams)
4302 { # remangling mode
4303 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004304 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004305 }
4306 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4307 $Mangled .= "C1";
4308 }
4309 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4310 $Mangled .= "D0";
4311 }
4312 elsif($ShortName)
4313 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004314 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4315 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004316 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004317 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004318 { # "const" global data is mangled as _ZL...
4319 $Mangled .= "L";
4320 }
4321 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004322 if($ShortName=~/\Aoperator(\W.*)\Z/)
4323 {
4324 my $Op = $1;
4325 $Op=~s/\A[ ]+//g;
4326 if(my $OpMngl = $OperatorMangling{$Op}) {
4327 $Mangled .= $OpMngl;
4328 }
4329 else { # conversion operator
4330 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4331 }
4332 }
4333 else {
4334 $Mangled .= length($ShortName).$ShortName;
4335 }
4336 if(@TParams)
4337 { # templates
4338 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004339 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004340 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4341 }
4342 $Mangled .= "E";
4343 }
4344 if(not $ClassId and @TParams) {
4345 add_substitution($ShortName, \%Repl, 0);
4346 }
4347 }
4348 if($ClassId or $NameSpace) {
4349 $Mangled .= "E";
4350 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004351 if(@TParams)
4352 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004353 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004354 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4355 }
4356 }
4357 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4358 {
4359 my @Params = ();
4360 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4361 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4362 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4363 }
4364 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4365 { # checking parameters
4366 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4367 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4368 }
4369 if(not @Params) {
4370 $Mangled .= "v";
4371 }
4372 }
4373 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4374 $Mangled = write_stdcxx_substitution($Mangled);
4375 if($Mangled eq "_Z") {
4376 return "";
4377 }
4378 return $Mangled;
4379}
4380
4381sub correct_incharge($$$)
4382{
4383 my ($InfoId, $LibVersion, $Mangled) = @_;
4384 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4385 {
4386 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004387 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004388 }
4389 }
4390 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4391 {
4392 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004393 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004394 }
4395 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004396 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004397 }
4398 }
4399 return $Mangled;
4400}
4401
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004402sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004403{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004404 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004405 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004406 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004407 return $Name;
4408 }
4409 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004410 while(my $CPos = find_center($TParams, "<"))
4411 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004412 $TParams = substr($TParams, $CPos);
4413 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004414 if($TParams=~s/\A<(.+)>\Z/$1/) {
4415 $Name=~s/<\Q$TParams\E>\Z//;
4416 }
4417 else
4418 { # error
4419 $TParams = "";
4420 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004421 return ($Name, $TParams);
4422}
4423
4424sub get_sub_ns($)
4425{
4426 my $Name = $_[0];
4427 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004428 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004429 {
4430 push(@NS, substr($Name, 0, $CPos));
4431 $Name = substr($Name, $CPos);
4432 $Name=~s/\A:://;
4433 }
4434 return (join("::", @NS), $Name);
4435}
4436
4437sub mangle_ns($$$)
4438{
4439 my ($Name, $LibVersion, $Repl) = @_;
4440 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4441 {
4442 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4443 $Mangled=~s/\AN(.+)E\Z/$1/;
4444 return $Mangled;
4445
4446 }
4447 else
4448 {
4449 my ($MangledNS, $SubNS) = ("", "");
4450 ($SubNS, $Name) = get_sub_ns($Name);
4451 if($SubNS) {
4452 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4453 }
4454 $MangledNS .= length($Name).$Name;
4455 add_substitution($MangledNS, $Repl, 0);
4456 return $MangledNS;
4457 }
4458}
4459
4460sub mangle_param($$$)
4461{
4462 my ($PTid, $LibVersion, $Repl) = @_;
4463 my ($MPrefix, $Mangled) = ("", "");
4464 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004465 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004466 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004467 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004468 if(not $BaseType_Name) {
4469 return "";
4470 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004471 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004472 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004473 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4474 while($Suffix=~/(&|\*|const)\Z/)
4475 {
4476 if($Suffix=~s/[ ]*&\Z//) {
4477 $MPrefix .= "R";
4478 }
4479 if($Suffix=~s/[ ]*\*\Z//) {
4480 $MPrefix .= "P";
4481 }
4482 if($Suffix=~s/[ ]*const\Z//)
4483 {
4484 if($MPrefix=~/R|P/
4485 or $Suffix=~/&|\*/) {
4486 $MPrefix .= "K";
4487 }
4488 }
4489 if($Suffix=~s/[ ]*volatile\Z//) {
4490 $MPrefix .= "V";
4491 }
4492 #if($Suffix=~s/[ ]*restrict\Z//) {
4493 #$MPrefix .= "r";
4494 #}
4495 }
4496 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4497 $Mangled .= $Token;
4498 }
4499 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4500 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004501 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004502 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004503 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004504 foreach (@TPos) {
4505 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4506 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004507 }
4508 elsif($TmplParams)
4509 { # remangling mode
4510 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004511 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004512 }
4513 my $MangledNS = "";
4514 my ($SubNS, $SName) = get_sub_ns($ShortName);
4515 if($SubNS) {
4516 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4517 }
4518 $MangledNS .= length($SName).$SName;
4519 if(@TParams) {
4520 add_substitution($MangledNS, $Repl, 0);
4521 }
4522 $Mangled .= "N".$MangledNS;
4523 if(@TParams)
4524 { # templates
4525 $Mangled .= "I";
4526 foreach my $TParam (@TParams) {
4527 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4528 }
4529 $Mangled .= "E";
4530 }
4531 $Mangled .= "E";
4532 }
4533 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4534 {
4535 if($BaseType{"Type"} eq "MethodPtr") {
4536 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4537 }
4538 else {
4539 $Mangled .= "PF";
4540 }
4541 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4542 my @Params = keys(%{$BaseType{"Param"}});
4543 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4544 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4545 }
4546 if(not @Params) {
4547 $Mangled .= "v";
4548 }
4549 $Mangled .= "E";
4550 }
4551 elsif($BaseType{"Type"} eq "FieldPtr")
4552 {
4553 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4554 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4555 }
4556 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4557 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4558 {
4559 if($Mangled eq $Optimized)
4560 {
4561 if($ShortName!~/::/)
4562 { # remove "N ... E"
4563 if($MPrefix) {
4564 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4565 }
4566 else {
4567 $Mangled=~s/\AN(.+)E\Z/$1/g;
4568 }
4569 }
4570 }
4571 else {
4572 $Mangled = $Optimized;
4573 }
4574 }
4575 add_substitution($Mangled, $Repl, 1);
4576 return $Mangled;
4577}
4578
4579sub mangle_template_param($$$)
4580{ # types + literals
4581 my ($TParam, $LibVersion, $Repl) = @_;
4582 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4583 return mangle_param($TPTid, $LibVersion, $Repl);
4584 }
4585 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4586 { # class_name<1u>::method(...)
4587 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4588 }
4589 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4590 { # class_name<(signed char)1>::method(...)
4591 return "L".$IntrinsicMangling{$1}.$2."E";
4592 }
4593 elsif($TParam eq "true")
4594 { # class_name<true>::method(...)
4595 return "Lb1E";
4596 }
4597 elsif($TParam eq "false")
4598 { # class_name<true>::method(...)
4599 return "Lb0E";
4600 }
4601 else { # internal error
4602 return length($TParam).$TParam;
4603 }
4604}
4605
4606sub add_substitution($$$)
4607{
4608 my ($Value, $Repl, $Rec) = @_;
4609 if($Rec)
4610 { # subtypes
4611 my @Subs = ($Value);
4612 while($Value=~s/\A(R|P|K)//) {
4613 push(@Subs, $Value);
4614 }
4615 foreach (reverse(@Subs)) {
4616 add_substitution($_, $Repl, 0);
4617 }
4618 return;
4619 }
4620 return if($Value=~/\AS(\d*)_\Z/);
4621 $Value=~s/\AN(.+)E\Z/$1/g;
4622 return if(defined $Repl->{$Value});
4623 return if(length($Value)<=1);
4624 return if($StdcxxMangling{$Value});
4625 # check for duplicates
4626 my $Base = $Value;
4627 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4628 {
4629 my $Num = $Repl->{$Type};
4630 my $Replace = macro_mangle($Num);
4631 $Base=~s/\Q$Replace\E/$Type/;
4632 }
4633 if(my $OldNum = $Repl->{$Base})
4634 {
4635 $Repl->{$Value} = $OldNum;
4636 return;
4637 }
4638 my @Repls = sort {$b<=>$a} values(%{$Repl});
4639 if(@Repls) {
4640 $Repl->{$Value} = $Repls[0]+1;
4641 }
4642 else {
4643 $Repl->{$Value} = -1;
4644 }
4645 # register duplicates
4646 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004647 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004648 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4649 {
4650 next if($Base eq $Type);
4651 my $Num = $Repl->{$Type};
4652 my $Replace = macro_mangle($Num);
4653 $Base=~s/\Q$Type\E/$Replace/;
4654 $Repl->{$Base} = $Repl->{$Value};
4655 }
4656}
4657
4658sub macro_mangle($)
4659{
4660 my $Num = $_[0];
4661 if($Num==-1) {
4662 return "S_";
4663 }
4664 else
4665 {
4666 my $Code = "";
4667 if($Num<10)
4668 { # S0_, S1_, S2_, ...
4669 $Code = $Num;
4670 }
4671 elsif($Num>=10 and $Num<=35)
4672 { # SA_, SB_, SC_, ...
4673 $Code = chr(55+$Num);
4674 }
4675 else
4676 { # S10_, S11_, S12_
4677 $Code = $Num-26; # 26 is length of english alphabet
4678 }
4679 return "S".$Code."_";
4680 }
4681}
4682
4683sub write_stdcxx_substitution($)
4684{
4685 my $Mangled = $_[0];
4686 if($StdcxxMangling{$Mangled}) {
4687 return $StdcxxMangling{$Mangled};
4688 }
4689 else
4690 {
4691 my @Repls = keys(%StdcxxMangling);
4692 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4693 foreach my $MangledType (@Repls)
4694 {
4695 my $Replace = $StdcxxMangling{$MangledType};
4696 #if($Mangled!~/$Replace/) {
4697 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4698 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4699 #}
4700 }
4701 }
4702 return $Mangled;
4703}
4704
4705sub write_substitution($$)
4706{
4707 my ($Mangled, $Repl) = @_;
4708 if(defined $Repl->{$Mangled}
4709 and my $MnglNum = $Repl->{$Mangled}) {
4710 $Mangled = macro_mangle($MnglNum);
4711 }
4712 else
4713 {
4714 my @Repls = keys(%{$Repl});
4715 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4716 # FIXME: how to apply replacements? by num or by pos
4717 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4718 foreach my $MangledType (@Repls)
4719 {
4720 my $Replace = macro_mangle($Repl->{$MangledType});
4721 if($Mangled!~/$Replace/) {
4722 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4723 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4724 }
4725 }
4726 }
4727 return $Mangled;
4728}
4729
4730sub delete_keywords($)
4731{
4732 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004733 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004734 return $TypeName;
4735}
4736
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004737sub uncover_typedefs($$)
4738{
4739 my ($TypeName, $LibVersion) = @_;
4740 return "" if(not $TypeName);
4741 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4742 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4743 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004744 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004745 while($TypeName_New ne $TypeName_Pre)
4746 {
4747 $TypeName_Pre = $TypeName_New;
4748 my $TypeName_Copy = $TypeName_New;
4749 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004750 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004751 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004752 if(not $Intrinsic_Keywords{$1}) {
4753 $Words{$1} = 1;
4754 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004755 }
4756 foreach my $Word (keys(%Words))
4757 {
4758 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4759 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004760 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004761 if($BaseType_Name=~/\([\*]+\)/)
4762 { # FuncPtr
4763 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4764 {
4765 my $Type_Suffix = $1;
4766 $TypeName_New = $BaseType_Name;
4767 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004768 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004769 }
4770 }
4771 }
4772 else
4773 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004774 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004775 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004776 }
4777 }
4778 }
4779 }
4780 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4781}
4782
4783sub isInternal($)
4784{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004785 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4786 {
4787 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4788 {
4789 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4790 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4791 return 1;
4792 }
4793 }
4794 }
4795 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004796}
4797
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004798sub getDataVal($$)
4799{
4800 my ($InfoId, $TypeId) = @_;
4801 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4802 {
4803 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4804 {
4805 if(defined $LibInfo{$Version}{"info_type"}{$1}
4806 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004807 {
4808 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004809 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004810 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4811 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004812 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004813 if(my $Addr = getTreeAttr_Op($1)) {
4814 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004815 }
4816 }
4817 }
4818 }
4819 else {
4820 return getInitVal($1, $TypeId);
4821 }
4822 }
4823 }
4824 return undef;
4825}
4826
4827sub getInitVal($$)
4828{
4829 my ($InfoId, $TypeId) = @_;
4830 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4831 {
4832 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4833 {
4834 if($InfoType eq "integer_cst")
4835 {
4836 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004837 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004838 { # characters
4839 $Val = chr($Val);
4840 }
4841 return $Val;
4842 }
4843 elsif($InfoType eq "string_cst") {
4844 return getNodeStrCst($InfoId);
4845 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004846 elsif($InfoType eq "var_decl")
4847 {
4848 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4849 return $Name;
4850 }
4851 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004852 }
4853 }
4854 return undef;
4855}
4856
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004857sub set_Class_And_Namespace($)
4858{
4859 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004860 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004861 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004862 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004863 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004864 my $NSInfoId = $1;
4865 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4866 {
4867 if($InfoType eq "namespace_decl") {
4868 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4869 }
4870 elsif($InfoType eq "record_type") {
4871 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4872 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004873 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004874 }
4875 }
4876 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4877 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004878 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004879 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004880 { # skip
4881 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004882 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004883 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004884
4885 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004886}
4887
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004888sub debugMangling($)
4889{
4890 my $LibVersion = $_[0];
4891 my %Mangled = ();
4892 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4893 {
4894 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4895 {
4896 if($Mngl=~/\A(_Z|\?)/) {
4897 $Mangled{$Mngl}=$InfoId;
4898 }
4899 }
4900 }
4901 translateSymbols(keys(%Mangled), $LibVersion);
4902 foreach my $Mngl (keys(%Mangled))
4903 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004904 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4905 my $U2 = $tr_name{$Mngl};
4906 if($U1 ne $U2) {
4907 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004908 }
4909 }
4910}
4911
4912sub linkSymbol($)
4913{ # link symbols from shared libraries
4914 # with the symbols from header files
4915 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004916 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004917 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004918 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4919 or $EMERGENCY_MODE_48)
4920 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4921 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
4922 # GCC 4.8 doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004923 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004924 {
4925 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4926 return correct_incharge($InfoId, $Version, $Mangled);
4927 }
4928 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004929 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004930 or not $BinaryOnly
4931 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004932 { # 1. --headers-only mode
4933 # 2. not mangled src-only symbols
4934 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4935 return $Mangled;
4936 }
4937 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004938 }
4939 return "";
4940}
4941
4942sub setLanguage($$)
4943{
4944 my ($LibVersion, $Lang) = @_;
4945 if(not $UserLang) {
4946 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4947 }
4948}
4949
4950sub getSymbolInfo($)
4951{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004952 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004953 if(isInternal($InfoId)) {
4954 return;
4955 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004956 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4957 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004958 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4959 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004960 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004961 return;
4962 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004963 setFuncAccess($InfoId);
4964 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004965 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4966 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004967 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004968 return;
4969 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004970
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004971 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004972 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004973 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004974 if(not defined $TypeInfo{$Version}{$Return}
4975 or not $TypeInfo{$Version}{$Return}{"Name"})
4976 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004977 delete($SymbolInfo{$Version}{$InfoId});
4978 return;
4979 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004980 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004981 }
4982 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
4983 {
4984 if(defined $MissedTypedef{$Version}{$Rid})
4985 {
4986 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
4987 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
4988 }
4989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004990 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004991 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
4992 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004993 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004994 my $Orig = getFuncOrig($InfoId);
4995 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004996 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
4997 {
4998 delete($SymbolInfo{$Version}{$InfoId});
4999 return;
5000 }
5001
5002 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005003 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005004 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005005 return;
5006 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005007
5008 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005009 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005010 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5011
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005012 my @TParams = getTParams($Orig, "Func");
5013 if(not @TParams)
5014 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005015 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005016 return;
5017 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005018 foreach my $Pos (0 .. $#TParams)
5019 {
5020 my $Val = $TParams[$Pos];
5021 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5022
5023 if($Tmpl)
5024 {
5025 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5026 {
5027 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5028 }
5029 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005030 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005031
5032 if($Tmpl)
5033 {
5034 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5035 {
5036 if($Pos>$#TParams)
5037 {
5038 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5039 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5040 }
5041 }
5042 }
5043
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005044 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5045 { # operator<< <T>, operator>> <T>
5046 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5047 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005048 if(@TParams) {
5049 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5050 }
5051 else {
5052 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5053 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005054 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005055 }
5056 else
5057 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005058 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005059 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005060 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5061 {
5062 if($OSgroup eq "windows")
5063 { # cut the offset
5064 $MnglName=~s/\@\d+\Z//g;
5065 }
5066 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5067
5068 # NOTE: mangling of some symbols may change depending on GCC version
5069 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5070 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5071 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005072
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005073 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005074 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005075 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005076 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005077 return;
5078 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005079 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005080 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005081 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005082 if($Skip)
5083 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005084 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005085 return;
5086 }
5087 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005088 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5089 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5090 }
5091
5092 if(set_Class_And_Namespace($InfoId))
5093 {
5094 delete($SymbolInfo{$Version}{$InfoId});
5095 return;
5096 }
5097
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005098 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5099 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005100 if(not defined $TypeInfo{$Version}{$ClassId}
5101 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5102 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005103 delete($SymbolInfo{$Version}{$InfoId});
5104 return;
5105 }
5106 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005107 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5108 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005109 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005110 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005111 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005112 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005113 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005114 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005115 }
5116 if($COMMON_LANGUAGE{$Version} eq "C++")
5117 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005118 # C++ or --headers-only mode
5119 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005120 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005121 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5122 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005123 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005124 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005125 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005126 if(my $Mangled = linkSymbol($InfoId)) {
5127 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005128 }
5129 }
5130 if($OStarget eq "windows")
5131 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005132 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005133 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005134 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005135 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005136 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005137 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005138 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005139 }
5140 }
5141 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005142 else
5143 { # not mangled in C
5144 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5145 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005146 if(not $CheckHeadersOnly
5147 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5148 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5149 {
5150 my $Incorrect = 0;
5151
5152 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5153 {
5154 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5155 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5156 { # mangled in the TU dump, but not mangled in the library
5157 $Incorrect = 1;
5158 }
5159 }
5160 else
5161 {
5162 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5163 { # all C++ functions are not mangled in the TU dump
5164 $Incorrect = 1;
5165 }
5166 }
5167 if($Incorrect)
5168 {
5169 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5170 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5171 }
5172 }
5173 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005174 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005175 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005176 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005177 return;
5178 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005179 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005180 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005181 { # identify virtual and pure virtual functions
5182 # NOTE: constructors cannot be virtual
5183 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5184 # in the TU dump, so taking it from the original symbol
5185 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5186 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5187 { # NOTE: D2 destructors are not present in a v-table
5188 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5189 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005190 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005191 if(isInline($InfoId)) {
5192 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005193 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005194 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005195 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5196 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005197 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5198 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005199 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005200 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005201 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005202 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005203 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005204 }
5205 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005206 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5207 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005208 if(not $ExtraDump)
5209 {
5210 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5211 { # non-target symbols
5212 delete($SymbolInfo{$Version}{$InfoId});
5213 return;
5214 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005215 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005216 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005217 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5218 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5219 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5220 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005221 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005222 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5223 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005224 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005225 return;
5226 }
5227 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005228 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005229 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005230 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005231 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005232 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005233 return;
5234 }
5235 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005236 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005237 }
5238 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005239 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5240 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5241 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005242 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005243 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5244 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005245 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005246 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005247 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005248 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005249 }
5250 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005251 if(getFuncLink($InfoId) eq "Static") {
5252 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005253 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005254 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5255 {
5256 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5257 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005258 if($Unmangled=~/\.\_\d/)
5259 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005260 delete($SymbolInfo{$Version}{$InfoId});
5261 return;
5262 }
5263 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005264 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005265
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005266 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5267 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005268 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005269 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5270 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005271 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005272
5273 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5274 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5275 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005276
5277 if($ExtraDump) {
5278 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5279 }
5280}
5281
5282sub guessHeader($)
5283{
5284 my $InfoId = $_[0];
5285 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5286 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5287 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5288 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5289 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5290 {
5291 if(get_filename($HPath) eq $Header)
5292 {
5293 my $HDir = get_filename(get_dirname($HPath));
5294 if($HDir ne "include"
5295 and $HDir=~/\A[a-z]+\Z/i) {
5296 return join_P($HDir, $Header);
5297 }
5298 }
5299 }
5300 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005301}
5302
5303sub isInline($)
5304{ # "body: undefined" in the tree
5305 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005306 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5307 {
5308 if($Info=~/ undefined /i) {
5309 return 0;
5310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005311 }
5312 return 1;
5313}
5314
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005315sub hasThrow($)
5316{
5317 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5318 {
5319 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5320 return getTreeAttr_Unql($1, "unql");
5321 }
5322 }
5323 return 1;
5324}
5325
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005326sub getTypeId($)
5327{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005328 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5329 {
5330 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5331 return $1;
5332 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005333 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005334 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005335}
5336
5337sub setTypeMemb($$)
5338{
5339 my ($TypeId, $TypeAttr) = @_;
5340 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005341 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005342 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005343 if($TypeType eq "Enum")
5344 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005345 my $MInfoId = getTreeAttr_Csts($TypeId);
5346 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005347 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005348 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5349 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005350 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005351 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5352 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005353 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005354 }
5355 }
5356 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5357 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005358 my $MInfoId = getTreeAttr_Flds($TypeId);
5359 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005360 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005361 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5362 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005363 if(not $IType or $IType ne "field_decl")
5364 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005365
5366 if($IType eq "var_decl")
5367 { # static field
5368 $StaticFields = 1;
5369 }
5370
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005371 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005372 next;
5373 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005374 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005375 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005376 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005377 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005378 }
5379 if(not $StructMembName)
5380 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005381 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005382 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005383 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005384 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5385 if(isAnon($UnnamedTName))
5386 { # rename unnamed fields to unnamed0, unnamed1, ...
5387 $StructMembName = "unnamed".($UnnamedPos++);
5388 }
5389 }
5390 }
5391 if(not $StructMembName)
5392 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005393 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005394 next;
5395 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005396 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005397 if(defined $MissedTypedef{$Version}{$MembTypeId})
5398 {
5399 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5400 $MembTypeId = $AddedTid;
5401 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005402 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005403
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005404 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5405 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005406 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005407 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005408 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5409 }
5410 if($MInfo=~/spec:\s*mutable /)
5411 { # mutable fields
5412 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005413 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005414 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005415 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5416 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005417 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005418 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005419 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005420 }
5421 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005422 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005423 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5424 { # template
5425 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5426 }
5427 else {
5428 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5429 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005430 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005431
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005432 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005433 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005434 }
5435 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005436
5437 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005438}
5439
5440sub setFuncParams($)
5441{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005442 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005443 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005444
5445 my $FType = getFuncType($InfoId);
5446
5447 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005448 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005449 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5450 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005451 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005452 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005453 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5454 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005455 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005456 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5457 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005458 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005459 else
5460 { # skip
5461 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005462 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005463 # skip "this"-parameter
5464 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005465 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005466 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005467 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005468 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005469 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5470 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5471 if(not $ParamName)
5472 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005473 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005474 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005475 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5476 {
5477 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5478 $ParamTypeId = $AddedTid;
5479 }
5480 }
5481 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005482 if(not $PType or $PType eq "Unknown") {
5483 return 1;
5484 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005485 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005486 if(not $PTName) {
5487 return 1;
5488 }
5489 if($PTName eq "void") {
5490 last;
5491 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005492 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005493 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005494 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005495 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005496 $ParamInfoId = getNextElem($ParamInfoId);
5497 next;
5498 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005499 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005500
5501 if(my %Base = get_BaseType($ParamTypeId, $Version))
5502 {
5503 if(defined $Base{"Template"}) {
5504 return 1;
5505 }
5506 }
5507
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005508 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005509 if(my $Algn = getAlgn($ParamInfoId)) {
5510 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5511 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005512 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5513 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005514 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005515 }
5516 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005517 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005518 if($ParamName ne "this" or $FType ne "Method") {
5519 $PPos += 1;
5520 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005521 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005522 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005523 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005524 }
5525 return 0;
5526}
5527
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005528sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005529{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005530 my ($InfoId, $Vtt_Pos) = @_;
5531 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005532 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005533 my $FType = getFuncType($InfoId);
5534
5535 if($FType eq "Method")
5536 {
5537 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005538 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005539 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005540 if(not $ParamListElemId)
5541 { # foo(...)
5542 return 1;
5543 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005544 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005545 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005546 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005547 { # actual params: may differ from formal args
5548 # formal int*const
5549 # actual: int*
5550 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005551 {
5552 $Vtt_Pos=-1;
5553 $ParamListElemId = getNextElem($ParamListElemId);
5554 next;
5555 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005556 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5557 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005558 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005559 $HaveVoid = 1;
5560 last;
5561 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005562 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005563 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005564 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5565 {
5566 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5567 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5568 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005569 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005570 }
5571 }
5572 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5573 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005574 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005575 { # params
5576 if($OldId ne $ParamTypeId)
5577 {
5578 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5579 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5580
5581 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5582 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5583 }
5584 }
5585 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005586 }
5587 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005588 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005589 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005590 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5591 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005592 if($PurpType eq "nop_expr")
5593 { # func ( const char* arg = (const char*)(void*)0 )
5594 $PurpId = getTreeAttr_Op($PurpId);
5595 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005596 my $Val = getInitVal($PurpId, $ParamTypeId);
5597 if(defined $Val) {
5598 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005600 }
5601 }
5602 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005603 if($Pos!=0 or $FType ne "Method") {
5604 $PPos += 1;
5605 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005606 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005607 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005608 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005609}
5610
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005611sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005612{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005613 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5614 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005615 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5616 return $1;
5617 }
5618 }
5619 return "";
5620}
5621
5622sub getTreeAttr_Chain($)
5623{
5624 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5625 {
5626 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5627 return $1;
5628 }
5629 }
5630 return "";
5631}
5632
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005633sub getTreeAttr_Unql($)
5634{
5635 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5636 {
5637 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5638 return $1;
5639 }
5640 }
5641 return "";
5642}
5643
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005644sub getTreeAttr_Scpe($)
5645{
5646 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5647 {
5648 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5649 return $1;
5650 }
5651 }
5652 return "";
5653}
5654
5655sub getTreeAttr_Type($)
5656{
5657 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5658 {
5659 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5660 return $1;
5661 }
5662 }
5663 return "";
5664}
5665
5666sub getTreeAttr_Name($)
5667{
5668 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5669 {
5670 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5671 return $1;
5672 }
5673 }
5674 return "";
5675}
5676
5677sub getTreeAttr_Mngl($)
5678{
5679 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5680 {
5681 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5682 return $1;
5683 }
5684 }
5685 return "";
5686}
5687
5688sub getTreeAttr_Prms($)
5689{
5690 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5691 {
5692 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5693 return $1;
5694 }
5695 }
5696 return "";
5697}
5698
5699sub getTreeAttr_Fncs($)
5700{
5701 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5702 {
5703 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5704 return $1;
5705 }
5706 }
5707 return "";
5708}
5709
5710sub getTreeAttr_Csts($)
5711{
5712 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5713 {
5714 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5715 return $1;
5716 }
5717 }
5718 return "";
5719}
5720
5721sub getTreeAttr_Purp($)
5722{
5723 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5724 {
5725 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5726 return $1;
5727 }
5728 }
5729 return "";
5730}
5731
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005732sub getTreeAttr_Op($)
5733{
5734 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5735 {
5736 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5737 return $1;
5738 }
5739 }
5740 return "";
5741}
5742
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005743sub getTreeAttr_Valu($)
5744{
5745 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5746 {
5747 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5748 return $1;
5749 }
5750 }
5751 return "";
5752}
5753
5754sub getTreeAttr_Flds($)
5755{
5756 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5757 {
5758 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5759 return $1;
5760 }
5761 }
5762 return "";
5763}
5764
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005765sub getTreeAttr_Binf($)
5766{
5767 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5768 {
5769 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5770 return $1;
5771 }
5772 }
5773 return "";
5774}
5775
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005776sub getTreeAttr_Args($)
5777{
5778 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5779 {
5780 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005781 return $1;
5782 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005783 }
5784 return "";
5785}
5786
5787sub getTreeValue($)
5788{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005789 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5790 {
5791 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5792 return $1;
5793 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005794 }
5795 return "";
5796}
5797
5798sub getTreeAccess($)
5799{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005800 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005801 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005802 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5803 {
5804 my $Access = $1;
5805 if($Access eq "prot") {
5806 return "protected";
5807 }
5808 elsif($Access eq "priv") {
5809 return "private";
5810 }
5811 }
5812 elsif($Info=~/ protected /)
5813 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005814 return "protected";
5815 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005816 elsif($Info=~/ private /)
5817 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005818 return "private";
5819 }
5820 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005821 return "public";
5822}
5823
5824sub setFuncAccess($)
5825{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005826 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005827 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005828 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005829 }
5830 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005831 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005832 }
5833}
5834
5835sub setTypeAccess($$)
5836{
5837 my ($TypeId, $TypeAttr) = @_;
5838 my $Access = getTreeAccess($TypeId);
5839 if($Access eq "protected") {
5840 $TypeAttr->{"Protected"} = 1;
5841 }
5842 elsif($Access eq "private") {
5843 $TypeAttr->{"Private"} = 1;
5844 }
5845}
5846
5847sub setFuncKind($)
5848{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005849 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5850 {
5851 if($Info=~/pseudo tmpl/) {
5852 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5853 }
5854 elsif($Info=~/ constructor /) {
5855 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5856 }
5857 elsif($Info=~/ destructor /) {
5858 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5859 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005860 }
5861}
5862
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005863sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005864{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005865 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5866 {
5867 if($Info=~/spec[ ]*:[ ]*pure /) {
5868 return "PureVirt";
5869 }
5870 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5871 return "Virt";
5872 }
5873 elsif($Info=~/ pure\s+virtual /)
5874 { # support for old GCC versions
5875 return "PureVirt";
5876 }
5877 elsif($Info=~/ virtual /)
5878 { # support for old GCC versions
5879 return "Virt";
5880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005881 }
5882 return "";
5883}
5884
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005885sub getFuncLink($)
5886{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005887 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5888 {
5889 if($Info=~/link[ ]*:[ ]*static /) {
5890 return "Static";
5891 }
5892 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005893 return $1;
5894 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005895 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005896 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005897}
5898
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005899sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005900{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005901 my ($Symbol, $LibVersion) = @_;
5902 return "" if(not $Symbol or not $LibVersion);
5903 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5904 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005905 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005906 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5907 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5908 }
5909 }
5910 if($NS)
5911 {
5912 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5913 return $NS;
5914 }
5915 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005916 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005917 while($NS=~s/::[^:]+\Z//)
5918 {
5919 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5920 return $NS;
5921 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005922 }
5923 }
5924 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005925
5926 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005927}
5928
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005929sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005930{
5931 my ($TypeName, $LibVersion) = @_;
5932 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005933 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005934 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005935 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5936 return $NS;
5937 }
5938 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005939 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005940 while($NS=~s/::[^:]+\Z//)
5941 {
5942 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5943 return $NS;
5944 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005945 }
5946 }
5947 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005948 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005949}
5950
5951sub getNameSpace($)
5952{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005953 my $InfoId = $_[0];
5954 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005955 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005956 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005957 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005958 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005959 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005960 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5961 {
5962 my $NameSpace = getTreeStr($1);
5963 if($NameSpace eq "::")
5964 { # global namespace
5965 return "";
5966 }
5967 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5968 $NameSpace = $BaseNameSpace."::".$NameSpace;
5969 }
5970 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5971 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005972 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005973 else {
5974 return "";
5975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005976 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005977 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005978 { # inside data type
5979 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
5980 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005981 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005983 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005984 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005985}
5986
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005987sub getEnumMembVal($)
5988{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005989 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005990 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005991 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
5992 {
5993 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
5994 {
5995 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
5996 { # in newer versions of GCC the value is in the "const_decl->cnst" node
5997 return getTreeValue($1);
5998 }
5999 else
6000 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6001 return getTreeValue($1);
6002 }
6003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006004 }
6005 }
6006 return "";
6007}
6008
6009sub getSize($)
6010{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006011 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6012 {
6013 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6014 return getTreeValue($1);
6015 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006016 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006017 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006018}
6019
6020sub getAlgn($)
6021{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006022 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6023 {
6024 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6025 return $1;
6026 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006027 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006028 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006029}
6030
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006031sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006032{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006033 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6034 {
6035 if($Info=~/ bitfield /) {
6036 return getSize($_[0]);
6037 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006038 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006039 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006040}
6041
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006042sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006043{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006044 if(my $Chan = getTreeAttr_Chan($_[0])) {
6045 return $Chan;
6046 }
6047 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6048 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006049 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006050 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006051}
6052
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006053sub registerHeader($$)
6054{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006055 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006056 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006057 return "";
6058 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006059 if(is_abs($Header) and not -f $Header)
6060 { # incorrect absolute path
6061 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006062 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006063 if(skipHeader($Header, $LibVersion))
6064 { # skip
6065 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006066 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006067 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6068 {
6069 detect_header_includes($Header_Path, $LibVersion);
6070
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006071 if(defined $Tolerance and $Tolerance=~/3/)
6072 { # 3 - skip headers that include non-Linux headers
6073 if($OSgroup ne "windows")
6074 {
6075 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6076 {
6077 if(specificHeader($Inc, "windows")) {
6078 return "";
6079 }
6080 }
6081 }
6082 }
6083
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006084 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6085 { # redirect
6086 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6087 or skipHeader($RHeader_Path, $LibVersion))
6088 { # skip
6089 return "";
6090 }
6091 $Header_Path = $RHeader_Path;
6092 }
6093 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6094 { # skip
6095 return "";
6096 }
6097
6098 if(my $HName = get_filename($Header_Path))
6099 { # register
6100 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6101 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6102 }
6103
6104 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6105 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006106 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006107 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006108 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006109 }
6110
6111 if($CheckHeadersOnly
6112 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6113 { # /usr/include/c++/4.6.1/...
6114 $STDCXX_TESTING = 1;
6115 }
6116
6117 return $Header_Path;
6118 }
6119 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006120}
6121
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006122sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006123{
6124 my ($Dir, $WithDeps, $LibVersion) = @_;
6125 $Dir=~s/[\/\\]+\Z//g;
6126 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006127 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006128
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006129 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006130 if($WithDeps)
6131 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006132 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6133 return;
6134 }
6135 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6136 $Mode = "DepsOnly";
6137 }
6138 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006139 else
6140 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006141 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6142 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6143 return;
6144 }
6145 }
6146 $Header_Dependency{$LibVersion}{$Dir} = 1;
6147 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6148 if($Mode eq "DepsOnly")
6149 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006150 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006151 $Header_Dependency{$LibVersion}{$Path} = 1;
6152 }
6153 return;
6154 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006155 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006156 {
6157 if($WithDeps)
6158 {
6159 my $SubDir = $Path;
6160 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6161 { # register all sub directories
6162 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6163 }
6164 }
6165 next if(is_not_header($Path));
6166 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006167 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006168 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006169 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6170 }
6171 }
6172 if(get_filename($Dir) eq "include")
6173 { # search for "lib/include/" directory
6174 my $LibDir = $Dir;
6175 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006176 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006177 }
6178 }
6179}
6180
6181sub parse_redirect($$$)
6182{
6183 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006184 my @Errors = ();
6185 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6186 push(@Errors, $1);
6187 }
6188 my $Redirect = "";
6189 foreach (@Errors)
6190 {
6191 s/\s{2,}/ /g;
6192 if(/(only|must\ include
6193 |update\ to\ include
6194 |replaced\ with
6195 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006196 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006197 {
6198 $Redirect = $2;
6199 last;
6200 }
6201 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6202 {
6203 $Redirect = $2;
6204 last;
6205 }
6206 elsif(/this\ header\ should\ not\ be\ used
6207 |programs\ should\ not\ directly\ include
6208 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6209 |is\ not\ supported\ API\ for\ general\ use
6210 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006211 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006212 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6213 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6214 }
6215 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006216 if($Redirect)
6217 {
6218 $Redirect=~s/\A<//g;
6219 $Redirect=~s/>\Z//g;
6220 }
6221 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006222}
6223
6224sub parse_includes($$)
6225{
6226 my ($Content, $Path) = @_;
6227 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006228 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006229 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006230 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006231 my $Method = substr($Header, 0, 1, "");
6232 substr($Header, length($Header)-1, 1, "");
6233 $Header = path_format($Header, $OSgroup);
6234 if($Method eq "\"" or is_abs($Header))
6235 {
6236 if(-e join_P(get_dirname($Path), $Header))
6237 { # relative path exists
6238 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006239 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006240 else
6241 { # include "..." that doesn't exist is equal to include <...>
6242 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006243 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006244 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006245 else {
6246 $Includes{$Header} = 1;
6247 }
6248 }
6249 if($ExtraInfo)
6250 {
6251 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6252 { # FT_FREETYPE_H
6253 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006254 }
6255 }
6256 return \%Includes;
6257}
6258
6259sub ignore_path($)
6260{
6261 my $Path = $_[0];
6262 if($Path=~/\~\Z/)
6263 {# skipping system backup files
6264 return 1;
6265 }
6266 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6267 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6268 return 1;
6269 }
6270 return 0;
6271}
6272
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006273sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006274{
6275 my ($ArrRef, $W) = @_;
6276 return if(length($W)<2);
6277 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6278}
6279
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006280sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006281{
6282 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006283
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006284 $H1=~s/\.[a-z]+\Z//ig;
6285 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006286
6287 my $Hname1 = get_filename($H1);
6288 my $Hname2 = get_filename($H2);
6289 my $HDir1 = get_dirname($H1);
6290 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006291 my $Dirname1 = get_filename($HDir1);
6292 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006293
6294 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6295 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6296
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006297 if($_[0] eq $_[1]
6298 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006299 return 0;
6300 }
6301 elsif($H1=~/\A\Q$H2\E/) {
6302 return 1;
6303 }
6304 elsif($H2=~/\A\Q$H1\E/) {
6305 return -1;
6306 }
6307 elsif($HDir1=~/\Q$Hname1\E/i
6308 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006309 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006310 return -1;
6311 }
6312 elsif($HDir2=~/\Q$Hname2\E/i
6313 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006314 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006315 return 1;
6316 }
6317 elsif($Hname1=~/\Q$Dirname1\E/i
6318 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006319 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006320 return -1;
6321 }
6322 elsif($Hname2=~/\Q$Dirname2\E/i
6323 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006324 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006325 return 1;
6326 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006327 elsif($Hname1=~/(config|lib|util)/i
6328 and $Hname2!~/(config|lib|util)/i)
6329 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006330 return -1;
6331 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006332 elsif($Hname2=~/(config|lib|util)/i
6333 and $Hname1!~/(config|lib|util)/i)
6334 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006335 return 1;
6336 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006337 else
6338 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006339 my $R1 = checkRelevance($H1);
6340 my $R2 = checkRelevance($H2);
6341 if($R1 and not $R2)
6342 { # libebook/e-book.h
6343 return -1;
6344 }
6345 elsif($R2 and not $R1)
6346 { # libebook/e-book.h
6347 return 1;
6348 }
6349 else
6350 {
6351 return (lc($H1) cmp lc($H2));
6352 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006353 }
6354}
6355
6356sub searchForHeaders($)
6357{
6358 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006359
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006360 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006361 registerGccHeaders();
6362
6363 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6364 { # c++ standard include paths
6365 registerCppHeaders();
6366 }
6367
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006368 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006369 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6370 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006371 {
6372 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006373 if($SystemRoot)
6374 {
6375 if(is_abs($Path)) {
6376 $Path = $SystemRoot.$Path;
6377 }
6378 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006379 if(not -e $Path) {
6380 exitStatus("Access_Error", "can't access \'$Path\'");
6381 }
6382 elsif(-f $Path) {
6383 exitStatus("Access_Error", "\'$Path\' - not a directory");
6384 }
6385 elsif(-d $Path)
6386 {
6387 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006388 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006389 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6390 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006391 }
6392 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006393 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006394 }
6395 }
6396 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006397 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006398 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6399 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006400
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006401 # registering directories
6402 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6403 {
6404 next if(not -e $Path);
6405 $Path = get_abs_path($Path);
6406 $Path = path_format($Path, $OSgroup);
6407 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006408 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006409 }
6410 elsif(-f $Path)
6411 {
6412 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006413 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006414 and not $LocalIncludes{$Dir})
6415 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006416 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006417 # if(my $OutDir = get_dirname($Dir))
6418 # { # registering the outer directory
6419 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6420 # and not $LocalIncludes{$OutDir}) {
6421 # registerDir($OutDir, 0, $LibVersion);
6422 # }
6423 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006424 }
6425 }
6426 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006427
6428 # clean memory
6429 %RegisteredDirs = ();
6430
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006431 # registering headers
6432 my $Position = 0;
6433 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6434 {
6435 if(is_abs($Dest) and not -e $Dest) {
6436 exitStatus("Access_Error", "can't access \'$Dest\'");
6437 }
6438 $Dest = path_format($Dest, $OSgroup);
6439 if(is_header($Dest, 1, $LibVersion))
6440 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006441 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006442 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6443 }
6444 }
6445 elsif(-d $Dest)
6446 {
6447 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006448 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006449 {
6450 next if(ignore_path($Path));
6451 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006452 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006453 push(@Registered, $HPath);
6454 }
6455 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006456 @Registered = sort {sortHeaders($a, $b)} @Registered;
6457 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006458 foreach my $Path (@Registered) {
6459 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6460 }
6461 }
6462 else {
6463 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6464 }
6465 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006466
6467 if(defined $Tolerance and $Tolerance=~/4/)
6468 { # 4 - skip headers included by others
6469 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6470 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006471 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006472 delete($Registered_Headers{$LibVersion}{$Path});
6473 }
6474 }
6475 }
6476
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006477 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6478 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006479 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006480 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006481 if(is_abs($Header) and not -f $Header) {
6482 exitStatus("Access_Error", "can't access file \'$Header\'");
6483 }
6484 $Header = path_format($Header, $OSgroup);
6485 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6486 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006487 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006488 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006489 }
6490 else {
6491 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6492 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006493 }
6494 }
6495 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6496 { # set relative paths (for duplicates)
6497 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6498 { # search for duplicates
6499 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6500 my $Prefix = get_dirname($FirstPath);
6501 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6502 { # detect a shortest distinguishing prefix
6503 my $NewPrefix = $1;
6504 my %Identity = ();
6505 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6506 {
6507 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6508 $Identity{$Path} = $1;
6509 }
6510 }
6511 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006512 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006513 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6514 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6515 }
6516 last;
6517 }
6518 $Prefix = $NewPrefix; # increase prefix
6519 }
6520 }
6521 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006522
6523 # clean memory
6524 %HeaderName_Paths = ();
6525
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006526 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6527 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006528 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006529 my ($Pos, $PairPos) = (-1, -1);
6530 my ($Path, $PairPath) = ();
6531 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6532 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6533 foreach my $Header_Path (@Paths)
6534 {
6535 if(get_filename($Header_Path) eq $PairName)
6536 {
6537 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6538 $PairPath = $Header_Path;
6539 }
6540 if(get_filename($Header_Path) eq $HeaderName)
6541 {
6542 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6543 $Path = $Header_Path;
6544 }
6545 }
6546 if($PairPos!=-1 and $Pos!=-1
6547 and int($PairPos)<int($Pos))
6548 {
6549 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6550 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6551 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6552 }
6553 }
6554 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6555 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6556 }
6557}
6558
6559sub detect_real_includes($$)
6560{
6561 my ($AbsPath, $LibVersion) = @_;
6562 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6563 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6564 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6565 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6566 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006567 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6568
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006569 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6570 return () if(not $Path);
6571 open(PREPROC, $Path);
6572 while(<PREPROC>)
6573 {
6574 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6575 {
6576 my $Include = path_format($1, $OSgroup);
6577 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6578 next;
6579 }
6580 if($Include eq $AbsPath) {
6581 next;
6582 }
6583 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6584 }
6585 }
6586 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006587 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6588}
6589
6590sub detect_header_includes($$)
6591{
6592 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006593 return if(not $LibVersion or not $Path);
6594 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6595 return;
6596 }
6597 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6598
6599 if(not -e $Path) {
6600 return;
6601 }
6602
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006603 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006604 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6605 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006606 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006607 {
6608 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006609 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006610 }
6611 if($RedirectPath ne $Path) {
6612 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6613 }
6614 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006615 else
6616 { # can't find
6617 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6618 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006619 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006620 if(my $Inc = parse_includes($Content, $Path))
6621 {
6622 foreach my $Include (keys(%{$Inc}))
6623 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006624 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006625
6626 if(defined $Tolerance and $Tolerance=~/4/)
6627 {
6628 if(my $HPath = identifyHeader($Include, $LibVersion))
6629 {
6630 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6631 }
6632 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006633 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006634 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006635}
6636
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006637sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006638{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006639 my $Path = $_[0];
6640 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006641 if($OStarget eq "symbian")
6642 {
6643 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6644 { # epoc32/include/libc/{stdio, ...}.h
6645 return 1;
6646 }
6647 }
6648 else
6649 {
6650 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6651 { # /usr/include/{stdio, ...}.h
6652 return 1;
6653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006654 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006655 return 0;
6656}
6657
6658sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006659{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006660 my $Dir = $_[0];
6661 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006662 if($OStarget eq "symbian")
6663 {
6664 if(get_filename($OutDir) eq "libc"
6665 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6666 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6667 return 1;
6668 }
6669 }
6670 else
6671 { # linux
6672 if($OutDir eq "/usr/include"
6673 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6674 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6675 return 1;
6676 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006677 }
6678 return 0;
6679}
6680
6681sub detect_recursive_includes($$)
6682{
6683 my ($AbsPath, $LibVersion) = @_;
6684 return () if(not $AbsPath);
6685 if(isCyclical(\@RecurInclude, $AbsPath)) {
6686 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6687 }
6688 my ($AbsDir, $Name) = separate_path($AbsPath);
6689 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006690 { # system GLIBC internals
6691 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006692 }
6693 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6694 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6695 }
6696 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006697
6698 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6699 { # skip /usr/include/c++/*/ headers
6700 return () if(not $ExtraInfo);
6701 }
6702
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006703 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006704 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006705 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006706 { # check "real" (non-"model") include paths
6707 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6708 pop(@RecurInclude);
6709 return @Paths;
6710 }
6711 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6712 detect_header_includes($AbsPath, $LibVersion);
6713 }
6714 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6715 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006716 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006717 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006718 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006719 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006720 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006721 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006722 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006723 }
6724 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006725 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006726 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006727 { # search for the nearest header
6728 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006729 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006730 if(-f $Candidate) {
6731 $HPath = $Candidate;
6732 }
6733 }
6734 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006735 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006736 }
6737 next if(not $HPath);
6738 if($HPath eq $AbsPath) {
6739 next;
6740 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006741
6742 if($Debug)
6743 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006744# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6745# {
6746# print STDERR "$AbsPath -> $HPath\n";
6747# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006748 }
6749
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006750 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6751 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006752 { # only include <...>, skip include "..." prefixes
6753 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6754 }
6755 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6756 {
6757 if($IncPath eq $AbsPath) {
6758 next;
6759 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006760 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6761 if($RIncType==-1)
6762 { # include "..."
6763 $RIncType = $IncType;
6764 }
6765 elsif($RIncType==2)
6766 {
6767 if($IncType!=-1) {
6768 $RIncType = $IncType;
6769 }
6770 }
6771 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006772 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6773 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6774 }
6775 }
6776 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6777 {
6778 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6779 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6780 { # distinguish math.h from glibc and math.h from the tested library
6781 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6782 last;
6783 }
6784 }
6785 }
6786 pop(@RecurInclude);
6787 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6788}
6789
6790sub find_in_framework($$$)
6791{
6792 my ($Header, $Framework, $LibVersion) = @_;
6793 return "" if(not $Header or not $Framework or not $LibVersion);
6794 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6795 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6796 }
6797 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6798 {
6799 if(get_filename($Dependency) eq $Framework
6800 and -f get_dirname($Dependency)."/".$Header) {
6801 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6802 }
6803 }
6804 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6805}
6806
6807sub find_in_defaults($)
6808{
6809 my $Header = $_[0];
6810 return "" if(not $Header);
6811 if(defined $Cache{"find_in_defaults"}{$Header}) {
6812 return $Cache{"find_in_defaults"}{$Header};
6813 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006814 foreach my $Dir (@DefaultIncPaths,
6815 @DefaultGccPaths,
6816 @DefaultCppPaths,
6817 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006818 {
6819 next if(not $Dir);
6820 if(-f $Dir."/".$Header) {
6821 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6822 }
6823 }
6824 return ($Cache{"find_in_defaults"}{$Header}="");
6825}
6826
6827sub cmp_paths($$)
6828{
6829 my ($Path1, $Path2) = @_;
6830 my @Parts1 = split(/[\/\\]/, $Path1);
6831 my @Parts2 = split(/[\/\\]/, $Path2);
6832 foreach my $Num (0 .. $#Parts1)
6833 {
6834 my $Part1 = $Parts1[$Num];
6835 my $Part2 = $Parts2[$Num];
6836 if($GlibcDir{$Part1}
6837 and not $GlibcDir{$Part2}) {
6838 return 1;
6839 }
6840 elsif($GlibcDir{$Part2}
6841 and not $GlibcDir{$Part1}) {
6842 return -1;
6843 }
6844 elsif($Part1=~/glib/
6845 and $Part2!~/glib/) {
6846 return 1;
6847 }
6848 elsif($Part1!~/glib/
6849 and $Part2=~/glib/) {
6850 return -1;
6851 }
6852 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6853 return $CmpRes;
6854 }
6855 }
6856 return 0;
6857}
6858
6859sub checkRelevance($)
6860{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006861 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006862 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006863
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006864 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006865 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006866 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006867
6868 my $Name = lc(get_filename($Path));
6869 my $Dir = lc(get_dirname($Path));
6870
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006871 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006872
6873 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006874 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006875 my $Len = length($Token);
6876 next if($Len<=1);
6877 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6878 { # include/evolution-data-server-1.4/libebook/e-book.h
6879 return 1;
6880 }
6881 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006882 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006883 return 1;
6884 }
6885 }
6886 return 0;
6887}
6888
6889sub checkFamily(@)
6890{
6891 my @Paths = @_;
6892 return 1 if($#Paths<=0);
6893 my %Prefix = ();
6894 foreach my $Path (@Paths)
6895 {
6896 if($SystemRoot) {
6897 $Path = cut_path_prefix($Path, $SystemRoot);
6898 }
6899 if(my $Dir = get_dirname($Path))
6900 {
6901 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6902 $Prefix{$Dir} += 1;
6903 $Prefix{get_dirname($Dir)} += 1;
6904 }
6905 }
6906 foreach (sort keys(%Prefix))
6907 {
6908 if(get_depth($_)>=3
6909 and $Prefix{$_}==$#Paths+1) {
6910 return 1;
6911 }
6912 }
6913 return 0;
6914}
6915
6916sub isAcceptable($$$)
6917{
6918 my ($Header, $Candidate, $LibVersion) = @_;
6919 my $HName = get_filename($Header);
6920 if(get_dirname($Header))
6921 { # with prefix
6922 return 1;
6923 }
6924 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6925 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6926 return 1;
6927 }
6928 if(checkRelevance($Candidate))
6929 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6930 return 1;
6931 }
6932 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6933 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6934 # /usr/include/qt4/Qt/qsslconfiguration.h
6935 return 1;
6936 }
6937 if($OStarget eq "symbian")
6938 {
6939 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6940 return 1;
6941 }
6942 }
6943 return 0;
6944}
6945
6946sub isRelevant($$$)
6947{ # disallow to search for "abstract" headers in too deep directories
6948 my ($Header, $Candidate, $LibVersion) = @_;
6949 my $HName = get_filename($Header);
6950 if($OStarget eq "symbian")
6951 {
6952 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6953 return 0;
6954 }
6955 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006956 if($OStarget ne "bsd")
6957 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006958 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6959 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6960 return 0;
6961 }
6962 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006963 if($OStarget ne "windows")
6964 {
6965 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6966 { # skip /usr/include/wine/msvcrt
6967 return 0;
6968 }
6969 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006970 if(not get_dirname($Header)
6971 and $Candidate=~/[\/\\]wx[\/\\]/)
6972 { # do NOT search in system /wx/ directory
6973 # for headers without a prefix: sstream.h
6974 return 0;
6975 }
6976 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
6977 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
6978 { # skip ../c++/3.3.3/ if using ../c++/4.5/
6979 return 0;
6980 }
6981 if($Candidate=~/[\/\\]asm-/
6982 and (my $Arch = getArch($LibVersion)) ne "unknown")
6983 { # arch-specific header files
6984 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
6985 {# skip ../asm-arm/ if using x86 architecture
6986 return 0;
6987 }
6988 }
6989 my @Candidates = getSystemHeaders($HName, $LibVersion);
6990 if($#Candidates==1)
6991 { # unique header
6992 return 1;
6993 }
6994 my @SCandidates = getSystemHeaders($Header, $LibVersion);
6995 if($#SCandidates==1)
6996 { # unique name
6997 return 1;
6998 }
6999 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7000 if(get_depth($Candidate)-$SystemDepth>=5)
7001 { # abstract headers in too deep directories
7002 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7003 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7004 return 0;
7005 }
7006 }
7007 if($Header eq "parser.h"
7008 and $Candidate!~/\/libxml2\//)
7009 { # select parser.h from xml2 library
7010 return 0;
7011 }
7012 if(not get_dirname($Header)
7013 and keys(%{$SystemHeaders{$HName}})>=3)
7014 { # many headers with the same name
7015 # like thread.h included without a prefix
7016 if(not checkFamily(@Candidates)) {
7017 return 0;
7018 }
7019 }
7020 return 1;
7021}
7022
7023sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007024{ # cache function
7025 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7026 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7027 }
7028 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7029}
7030
7031sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007032{
7033 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007034 if(-f $Header) {
7035 return $Header;
7036 }
7037 if(is_abs($Header) and not -f $Header)
7038 { # incorrect absolute path
7039 return "";
7040 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007041 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007042 { # too abstract configuration headers
7043 return "";
7044 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007045 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007046 if($OSgroup ne "windows")
7047 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007048 if(defined $WinHeaders{lc($HName)}
7049 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007050 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007051 return "";
7052 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007053 }
7054 if($OSgroup ne "macos")
7055 {
7056 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007057 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007058 return "";
7059 }
7060 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007061
7062 if(defined $ObsoleteHeaders{$HName})
7063 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007064 return "";
7065 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007066 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7067 {
7068 if(defined $AlienHeaders{$HName}
7069 or defined $AlienHeaders{$Header})
7070 { # alien headers from other systems
7071 return "";
7072 }
7073 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007074
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007075 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007076 { # search in default paths
7077 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007078 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007079 }
7080 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007081 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007082 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007083 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007084 }
7085 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7086 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7087 {
7088 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007089 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007090 }
7091 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007092 # error
7093 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007094}
7095
7096sub getSystemHeaders($$)
7097{
7098 my ($Header, $LibVersion) = @_;
7099 my @Candidates = ();
7100 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7101 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007102 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007103 next;
7104 }
7105 push(@Candidates, $Candidate);
7106 }
7107 return @Candidates;
7108}
7109
7110sub cut_path_prefix($$)
7111{
7112 my ($Path, $Prefix) = @_;
7113 return $Path if(not $Prefix);
7114 $Prefix=~s/[\/\\]+\Z//;
7115 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7116 return $Path;
7117}
7118
7119sub is_default_include_dir($)
7120{
7121 my $Dir = $_[0];
7122 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007123 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007124}
7125
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007126sub identifyHeader($$)
7127{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007128 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007129 if(not $Header) {
7130 return "";
7131 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007132 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007133 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7134 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007135 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007136 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007137}
7138
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007139sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007140{ # search for header by absolute path, relative path or name
7141 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007142 if(-f $Header)
7143 { # it's relative or absolute path
7144 return get_abs_path($Header);
7145 }
7146 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7147 and my $HeaderDir = find_in_defaults($Header))
7148 { # search for libc headers in the /usr/include
7149 # for non-libc target library before searching
7150 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007151 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007152 }
7153 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7154 { # search in the target library paths
7155 return $Path;
7156 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007157 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007158 { # search in the internal GCC include paths
7159 return $DefaultGccHeader{$Header};
7160 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007161 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007162 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007163 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007164 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007165 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007166 { # search in the default G++ include paths
7167 return $DefaultCppHeader{$Header};
7168 }
7169 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7170 { # search everywhere in the system
7171 return $AnyPath;
7172 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007173 elsif($OSgroup eq "macos")
7174 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7175 if(my $Dir = get_dirname($Header))
7176 {
7177 my $RelPath = "Headers\/".get_filename($Header);
7178 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007179 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007180 }
7181 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007182 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007183 # cannot find anything
7184 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007185}
7186
7187sub getLocation($)
7188{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007189 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7190 {
7191 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007192 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007193 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007194 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007195 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007196}
7197
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007198sub getNameByInfo($)
7199{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007200 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007201 {
7202 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7203 {
7204 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7205 {
7206 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7207 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007208 my $Str = $1;
7209 if($CppMode{$Version}
7210 and $Str=~/\Ac99_(.+)\Z/)
7211 {
7212 if($CppKeywords_A{$1}) {
7213 $Str=$1;
7214 }
7215 }
7216 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007217 }
7218 }
7219 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007220 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007221 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007222}
7223
7224sub getTreeStr($)
7225{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007226 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007227 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007228 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7229 {
7230 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007231 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007232 and $Str=~/\Ac99_(.+)\Z/)
7233 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007234 if($CppKeywords_A{$1}) {
7235 $Str=$1;
7236 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007237 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007238 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007239 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007240 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007241 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007242}
7243
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007244sub getFuncShortName($)
7245{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007246 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007247 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007248 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007249 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007250 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007251 {
7252 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7253 {
7254 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7255 return "operator ".$RName;
7256 }
7257 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007258 }
7259 else
7260 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007261 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7262 {
7263 if(my $Ind = $Operator_Indication{$1}) {
7264 return "operator".$Ind;
7265 }
7266 elsif(not $UnknownOperator{$1})
7267 {
7268 printMsg("WARNING", "unknown operator $1");
7269 $UnknownOperator{$1} = 1;
7270 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007271 }
7272 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007273 }
7274 else
7275 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007276 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7277 return getTreeStr($1);
7278 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007279 }
7280 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007281 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007282}
7283
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007284sub getFuncReturn($)
7285{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007286 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7287 {
7288 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7289 {
7290 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7291 return $1;
7292 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007293 }
7294 }
7295 return "";
7296}
7297
7298sub getFuncOrig($)
7299{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007300 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7301 {
7302 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7303 return $1;
7304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007305 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007306 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007307}
7308
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007309sub unmangleArray(@)
7310{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007311 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007312 { # MSVC mangling
7313 my $UndNameCmd = get_CmdPath("undname");
7314 if(not $UndNameCmd) {
7315 exitStatus("Not_Found", "can't find \"undname\"");
7316 }
7317 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007318 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007319 }
7320 else
7321 { # GCC mangling
7322 my $CppFiltCmd = get_CmdPath("c++filt");
7323 if(not $CppFiltCmd) {
7324 exitStatus("Not_Found", "can't find c++filt in PATH");
7325 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007326 if(not defined $CPPFILT_SUPPORT_FILE)
7327 {
7328 my $Info = `$CppFiltCmd -h 2>&1`;
7329 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7330 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007331 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007332 if($CPPFILT_SUPPORT_FILE)
7333 { # new versions of c++filt can take a file
7334 if($#_>$MAX_CPPFILT_FILE_SIZE)
7335 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7336 # this is fixed in the oncoming version of Binutils
7337 my @Half = splice(@_, 0, ($#_+1)/2);
7338 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007339 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007340 else
7341 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007342 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7343 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7344 if($?==139)
7345 { # segmentation fault
7346 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7347 }
7348 return split(/\n/, $Res);
7349 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007350 }
7351 else
7352 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007353 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7354 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007355 my @Half = splice(@_, 0, ($#_+1)/2);
7356 return (unmangleArray(@Half), unmangleArray(@_))
7357 }
7358 else
7359 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007360 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007361 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7362 if($?==139)
7363 { # segmentation fault
7364 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7365 }
7366 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007367 }
7368 }
7369 }
7370}
7371
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007372sub get_ChargeLevel($$)
7373{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007374 my ($Symbol, $LibVersion) = @_;
7375 return "" if($Symbol!~/\A(_Z|\?)/);
7376 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7377 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007378 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007379 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007380 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007381 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007382 return "[in-charge]";
7383 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007384 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007385 return "[not-in-charge]";
7386 }
7387 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007388 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007389 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007390 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007391 return "[in-charge]";
7392 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007393 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007394 return "[not-in-charge]";
7395 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007396 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007397 return "[in-charge-deleting]";
7398 }
7399 }
7400 }
7401 else
7402 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007403 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007404 return "[in-charge]";
7405 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007406 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007407 return "[not-in-charge]";
7408 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007409 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007410 return "[in-charge]";
7411 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007412 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007413 return "[not-in-charge]";
7414 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007415 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007416 return "[in-charge-deleting]";
7417 }
7418 }
7419 return "";
7420}
7421
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007422sub get_Signature_M($$)
7423{
7424 my ($Symbol, $LibVersion) = @_;
7425 my $Signature_M = $tr_name{$Symbol};
7426 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7427 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007428 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007429 }
7430 return $Signature_M;
7431}
7432
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007433sub get_Signature($$)
7434{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007435 my ($Symbol, $LibVersion) = @_;
7436 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7437 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007438 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007439 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007440 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007441
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007442 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7443 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007444 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007445 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7446 {
7447 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7448 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7449 $Signature .= "~";
7450 }
7451 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007452 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007453 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007454 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007455 }
7456 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007457 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007458 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007459 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7460 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007461 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007462 else
7463 {
7464 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007465 }
7466 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007467 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007468 {
7469 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007470 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007471 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007472 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007473 if(not $ParamTypeName) {
7474 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7475 }
7476 foreach my $Typedef (keys(%ChangedTypedef))
7477 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007478 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7479 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7480 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007481 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007482 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7483 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007484 if($ParamName eq "this"
7485 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007486 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007487 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007488 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007489 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007490 }
7491 else {
7492 push(@ParamArray, $ParamTypeName);
7493 }
7494 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007495 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7496 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007497 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007498 }
7499 else
7500 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007501 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007502 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007503 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007504 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007505 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007506 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7507 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007508 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007509 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007510 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7511 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007512 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007513 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007514 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7515 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007516 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007517 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007518 }
7519 }
7520 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007521 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007522 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007523 }
7524 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007525 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007526 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007527 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007528}
7529
7530sub create_member_decl($$)
7531{
7532 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007533 if($TName=~/\([\*]+\)/)
7534 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007535 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7536 return $TName;
7537 }
7538 else
7539 {
7540 my @ArraySizes = ();
7541 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7542 push(@ArraySizes, $1);
7543 }
7544 return $TName." ".$Member.join("", @ArraySizes);
7545 }
7546}
7547
7548sub getFuncType($)
7549{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007550 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7551 {
7552 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7553 {
7554 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7555 {
7556 if($Type eq "method_type") {
7557 return "Method";
7558 }
7559 elsif($Type eq "function_type") {
7560 return "Function";
7561 }
7562 else {
7563 return "Other";
7564 }
7565 }
7566 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007567 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007568 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007569}
7570
7571sub getFuncTypeId($)
7572{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007573 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7574 {
7575 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7576 return $1;
7577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007578 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007579 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007580}
7581
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007582sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007583{ # "._N" or "$_N" in older GCC versions
7584 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007585}
7586
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007587sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007588{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007589 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7590 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007591 }
7592
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007593 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007594
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007595 if($_[1] ne "S")
7596 {
7597 $N=~s/\A[ ]+//g;
7598 $N=~s/[ ]+\Z//g;
7599 $N=~s/[ ]{2,}/ /g;
7600 }
7601
7602 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007603
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007604 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007605
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007606 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7607 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007608
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007609 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007610
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007611 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007612
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007613 if($_[1] eq "S")
7614 {
7615 if(index($N, "operator")!=-1) {
7616 $N=~s/\b(operator[ ]*)> >/$1>>/;
7617 }
7618 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007619
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007620 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007621}
7622
7623sub get_HeaderDeps($$)
7624{
7625 my ($AbsPath, $LibVersion) = @_;
7626 return () if(not $AbsPath or not $LibVersion);
7627 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7628 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7629 }
7630 my %IncDir = ();
7631 detect_recursive_includes($AbsPath, $LibVersion);
7632 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7633 {
7634 next if(not $HeaderPath);
7635 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7636 my $Dir = get_dirname($HeaderPath);
7637 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7638 {
7639 my $Dep = $Dir;
7640 if($Prefix)
7641 {
7642 if($OSgroup eq "windows")
7643 { # case insensitive seach on windows
7644 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7645 next;
7646 }
7647 }
7648 elsif($OSgroup eq "macos")
7649 { # seach in frameworks
7650 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7651 {
7652 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7653 {# frameworks
7654 my ($HFramework, $HName) = ($1, $2);
7655 $Dep = $HFramework;
7656 }
7657 else
7658 {# mismatch
7659 next;
7660 }
7661 }
7662 }
7663 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7664 { # Linux, FreeBSD
7665 next;
7666 }
7667 }
7668 if(not $Dep)
7669 { # nothing to include
7670 next;
7671 }
7672 if(is_default_include_dir($Dep))
7673 { # included by the compiler
7674 next;
7675 }
7676 if(get_depth($Dep)==1)
7677 { # too short
7678 next;
7679 }
7680 if(isLibcDir($Dep))
7681 { # do NOT include /usr/include/{sys,bits}
7682 next;
7683 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007684 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007685 }
7686 }
7687 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7688 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7689}
7690
7691sub sortIncPaths($$)
7692{
7693 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007694 if(not $ArrRef or $#{$ArrRef}<0) {
7695 return $ArrRef;
7696 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007697 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7698 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007699 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007700 return $ArrRef;
7701}
7702
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007703sub sortDeps($$$)
7704{
7705 if($Header_Dependency{$_[2]}{$_[0]}
7706 and not $Header_Dependency{$_[2]}{$_[1]}) {
7707 return 1;
7708 }
7709 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7710 and $Header_Dependency{$_[2]}{$_[1]}) {
7711 return -1;
7712 }
7713 return 0;
7714}
7715
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007716sub join_P($$)
7717{
7718 my $S = "/";
7719 if($OSgroup eq "windows") {
7720 $S = "\\";
7721 }
7722 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007723}
7724
7725sub get_namespace_additions($)
7726{
7727 my $NameSpaces = $_[0];
7728 my ($Additions, $AddNameSpaceId) = ("", 1);
7729 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7730 {
7731 next if($SkipNameSpaces{$Version}{$NS});
7732 next if(not $NS or $NameSpaces->{$NS}==-1);
7733 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7734 next if($NS=~/\A__/i);
7735 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007736 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007737 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7738 my @NS_Parts = split(/::/, $NS);
7739 next if($#NS_Parts==-1);
7740 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7741 foreach my $NS_Part (@NS_Parts)
7742 {
7743 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7744 $TypeDecl_Suffix .= "}";
7745 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007746 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007747 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7748 $Additions.=" $TypeDecl\n $FuncDecl\n";
7749 $AddNameSpaceId+=1;
7750 }
7751 return $Additions;
7752}
7753
7754sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007755{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007756 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007757 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007758 if($Fmt eq "windows")
7759 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007760 $Path=~s/\//\\/g;
7761 $Path=lc($Path);
7762 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007763 else
7764 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007765 $Path=~s/\\/\//g;
7766 }
7767 return $Path;
7768}
7769
7770sub inc_opt($$)
7771{
7772 my ($Path, $Style) = @_;
7773 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007774 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007775 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007776 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007777 return "-I\"".path_format($Path, "unix")."\"";
7778 }
7779 elsif($OSgroup eq "macos"
7780 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007781 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007782 return "-F".esc(get_dirname($Path));
7783 }
7784 else {
7785 return "-I".esc($Path);
7786 }
7787 }
7788 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007789 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007790 }
7791 return "";
7792}
7793
7794sub platformSpecs($)
7795{
7796 my $LibVersion = $_[0];
7797 my $Arch = getArch($LibVersion);
7798 if($OStarget eq "symbian")
7799 { # options for GCCE compiler
7800 my %Symbian_Opts = map {$_=>1} (
7801 "-D__GCCE__",
7802 "-DUNICODE",
7803 "-fexceptions",
7804 "-D__SYMBIAN32__",
7805 "-D__MARM_INTERWORK__",
7806 "-D_UNICODE",
7807 "-D__S60_50__",
7808 "-D__S60_3X__",
7809 "-D__SERIES60_3X__",
7810 "-D__EPOC32__",
7811 "-D__MARM__",
7812 "-D__EABI__",
7813 "-D__MARM_ARMV5__",
7814 "-D__SUPPORT_CPP_EXCEPTIONS__",
7815 "-march=armv5t",
7816 "-mapcs",
7817 "-mthumb-interwork",
7818 "-DEKA2",
7819 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7820 );
7821 return join(" ", keys(%Symbian_Opts));
7822 }
7823 elsif($OSgroup eq "windows"
7824 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7825 { # add options to MinGW compiler
7826 # to simulate the MSVC compiler
7827 my %MinGW_Opts = map {$_=>1} (
7828 "-D_WIN32",
7829 "-D_STDCALL_SUPPORTED",
7830 "-D__int64=\"long long\"",
7831 "-D__int32=int",
7832 "-D__int16=short",
7833 "-D__int8=char",
7834 "-D__possibly_notnullterminated=\" \"",
7835 "-D__nullterminated=\" \"",
7836 "-D__nullnullterminated=\" \"",
7837 "-D__w64=\" \"",
7838 "-D__ptr32=\" \"",
7839 "-D__ptr64=\" \"",
7840 "-D__forceinline=inline",
7841 "-D__inline=inline",
7842 "-D__uuidof(x)=IID()",
7843 "-D__try=",
7844 "-D__except(x)=",
7845 "-D__declspec(x)=__attribute__((x))",
7846 "-D__pragma(x)=",
7847 "-D_inline=inline",
7848 "-D__forceinline=__inline",
7849 "-D__stdcall=__attribute__((__stdcall__))",
7850 "-D__cdecl=__attribute__((__cdecl__))",
7851 "-D__fastcall=__attribute__((__fastcall__))",
7852 "-D__thiscall=__attribute__((__thiscall__))",
7853 "-D_stdcall=__attribute__((__stdcall__))",
7854 "-D_cdecl=__attribute__((__cdecl__))",
7855 "-D_fastcall=__attribute__((__fastcall__))",
7856 "-D_thiscall=__attribute__((__thiscall__))",
7857 "-DSHSTDAPI_(x)=x",
7858 "-D_MSC_EXTENSIONS",
7859 "-DSECURITY_WIN32",
7860 "-D_MSC_VER=1500",
7861 "-D_USE_DECLSPECS_FOR_SAL",
7862 "-D__noop=\" \"",
7863 "-DDECLSPEC_DEPRECATED=\" \"",
7864 "-D__builtin_alignof(x)=__alignof__(x)",
7865 "-DSORTPP_PASS");
7866 if($Arch eq "x86") {
7867 $MinGW_Opts{"-D_M_IX86=300"}=1;
7868 }
7869 elsif($Arch eq "x86_64") {
7870 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7871 }
7872 elsif($Arch eq "ia64") {
7873 $MinGW_Opts{"-D_M_IA64=300"}=1;
7874 }
7875 return join(" ", keys(%MinGW_Opts));
7876 }
7877 return "";
7878}
7879
7880my %C_Structure = map {$_=>1} (
7881# FIXME: Can't separate union and struct data types before dumping,
7882# so it sometimes cause compilation errors for unknown reason
7883# when trying to declare TYPE* tmp_add_class_N
7884# This is a list of such structures + list of other C structures
7885 "sigval",
7886 "sigevent",
7887 "sigaction",
7888 "sigvec",
7889 "sigstack",
7890 "timeval",
7891 "timezone",
7892 "rusage",
7893 "rlimit",
7894 "wait",
7895 "flock",
7896 "stat",
7897 "_stat",
7898 "stat32",
7899 "_stat32",
7900 "stat64",
7901 "_stat64",
7902 "_stati64",
7903 "if_nameindex",
7904 "usb_device",
7905 "sigaltstack",
7906 "sysinfo",
7907 "timeLocale",
7908 "tcp_debug",
7909 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007910 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007911 "timespec",
7912 "random_data",
7913 "drand48_data",
7914 "_IO_marker",
7915 "_IO_FILE",
7916 "lconv",
7917 "sched_param",
7918 "tm",
7919 "itimerspec",
7920 "_pthread_cleanup_buffer",
7921 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007922 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007923 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007924 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007925 "sigcontext",
7926 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007927 # Mac
7928 "_timex",
7929 "_class_t",
7930 "_category_t",
7931 "_class_ro_t",
7932 "_protocol_t",
7933 "_message_ref_t",
7934 "_super_message_ref_t",
7935 "_ivar_t",
7936 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007937);
7938
7939sub getCompileCmd($$$)
7940{
7941 my ($Path, $Opt, $Inc) = @_;
7942 my $GccCall = $GCC_PATH;
7943 if($Opt) {
7944 $GccCall .= " ".$Opt;
7945 }
7946 $GccCall .= " -x ";
7947 if($OSgroup eq "macos") {
7948 $GccCall .= "objective-";
7949 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007950
7951 if($EMERGENCY_MODE_48)
7952 { # workaround for GCC 4.8 (C only)
7953 $GccCall .= "c++";
7954 }
7955 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007956 { # compile as "C++" header
7957 # to obtain complete dump using GCC 4.0
7958 $GccCall .= "c++-header";
7959 }
7960 else
7961 { # compile as "C++" source
7962 # GCC 3.3 cannot compile headers
7963 $GccCall .= "c++";
7964 }
7965 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007966 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007967 $GccCall .= " ".$Opts;
7968 }
7969 # allow extra qualifications
7970 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007971 $GccCall .= " -fpermissive";
7972 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007973 if($NoStdInc)
7974 {
7975 $GccCall .= " -nostdinc";
7976 $GccCall .= " -nostdinc++";
7977 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007978 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007979 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007980 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007981 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007982 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007983 if($Inc)
7984 { # include paths
7985 $GccCall .= " ".$Inc;
7986 }
7987 return $GccCall;
7988}
7989
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007990sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007991{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007992 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007993 my %HeaderElems = (
7994 # Types
7995 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007996 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007997 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
7998 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007999 "time.h" => ["time_t"],
8000 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008001 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8002 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008003 "stdbool.h" => ["_Bool"],
8004 "rpc/xdr.h" => ["bool_t"],
8005 "in_systm.h" => ["n_long", "n_short"],
8006 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008007 "arpa/inet.h" => ["fw_src", "ip_src"],
8008 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008009 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008010 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008011 );
8012 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008013 foreach (keys(%HeaderElems))
8014 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008015 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008016 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008017 }
8018 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008019 my %Types = ();
8020 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8021 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008022 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008023 }
8024 if(keys(%Types))
8025 {
8026 my %AddHeaders = ();
8027 foreach my $Type (keys(%Types))
8028 {
8029 if(my $Header = $AutoPreamble{$Type})
8030 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008031 if(my $Path = identifyHeader($Header, $LibVersion))
8032 {
8033 if(skipHeader($Path, $LibVersion)) {
8034 next;
8035 }
8036 $Path = path_format($Path, $OSgroup);
8037 $AddHeaders{$Path}{"Type"} = $Type;
8038 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008039 }
8040 }
8041 }
8042 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008043 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008044 }
8045 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008046 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008047}
8048
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008049sub checkCTags($)
8050{
8051 my $Path = $_[0];
8052 if(not $Path) {
8053 return;
8054 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008055 my $CTags = undef;
8056
8057 if($OSgroup eq "bsd")
8058 { # use ectags on BSD
8059 $CTags = get_CmdPath("ectags");
8060 if(not $CTags) {
8061 printMsg("WARNING", "can't find \'ectags\' program");
8062 }
8063 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008064 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008065 $CTags = get_CmdPath("ctags");
8066 }
8067 if(not $CTags)
8068 {
8069 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008070 return;
8071 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008072
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008073 if($OSgroup ne "linux")
8074 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008075 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8076 if($Info!~/exuberant/i)
8077 {
8078 printMsg("WARNING", "incompatible version of \'ctags\' program");
8079 return;
8080 }
8081 }
8082
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008083 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008084 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008085 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008086 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008087 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008088 open(CTAGS, "<", $Out);
8089 while(my $Line = <CTAGS>)
8090 {
8091 chomp($Line);
8092 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008093 if(defined $Intrinsic_Keywords{$Name})
8094 { # noise
8095 next;
8096 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008097 if($Type eq "n")
8098 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008099 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008100 next;
8101 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008102 if(index($Scpe, "struct:")==0) {
8103 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008104 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008105 if(index($Scpe, "namespace:")==0)
8106 {
8107 if($Scpe=~s/\Anamespace://) {
8108 $Name = $Scpe."::".$Name;
8109 }
8110 }
8111 $TUnit_NameSpaces{$Version}{$Name} = 1;
8112 }
8113 elsif($Type eq "p")
8114 {
8115 if(not $Scpe or index($Scpe, "namespace:")==0) {
8116 $TUnit_Funcs{$Version}{$Name} = 1;
8117 }
8118 }
8119 elsif($Type eq "x")
8120 {
8121 if(not $Scpe or index($Scpe, "namespace:")==0) {
8122 $TUnit_Vars{$Version}{$Name} = 1;
8123 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008124 }
8125 }
8126 close(CTAGS);
8127}
8128
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008129sub preChange($$)
8130{
8131 my ($HeaderPath, $IncStr) = @_;
8132
8133 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8134 my $Content = undef;
8135
8136 if($OStarget eq "windows"
8137 and get_dumpmachine($GCC_PATH)=~/mingw/i
8138 and $MinGWMode{$Version}!=-1)
8139 { # modify headers to compile by MinGW
8140 if(not $Content)
8141 { # preprocessing
8142 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8143 }
8144 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8145 { # __asm { ... }
8146 $MinGWMode{$Version}=1;
8147 }
8148 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8149 { # comments after preprocessing
8150 $MinGWMode{$Version}=1;
8151 }
8152 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8153 { # 0xffui8
8154 $MinGWMode{$Version}=1;
8155 }
8156
8157 if($MinGWMode{$Version}) {
8158 printMsg("INFO", "Using MinGW compatibility mode");
8159 }
8160 }
8161
8162 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8163 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8164 { # rename C++ keywords in C code
8165 # disable this code by -cpp-compatible option
8166 if(not $Content)
8167 { # preprocessing
8168 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8169 }
8170 my $RegExp_C = join("|", keys(%CppKeywords_C));
8171 my $RegExp_F = join("|", keys(%CppKeywords_F));
8172 my $RegExp_O = join("|", keys(%CppKeywords_O));
8173
8174 my $Detected = undef;
8175
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008176 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 +04008177 { # MATCH:
8178 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008179 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008180 # unsigned private: 8;
8181 # DO NOT MATCH:
8182 # #pragma GCC visibility push(default)
8183 $CppMode{$Version} = 1;
8184 $Detected = "$1$2$3$4" if(not defined $Detected);
8185 }
8186 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8187 { # MATCH:
8188 # int delete(...);
8189 # int explicit(...);
8190 # DO NOT MATCH:
8191 # void operator delete(...)
8192 $CppMode{$Version} = 1;
8193 $Detected = "$1$2$3" if(not defined $Detected);
8194 }
8195 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8196 { # MATCH:
8197 # int bool;
8198 # DO NOT MATCH:
8199 # bool X;
8200 # return *this;
8201 # throw;
8202 $CppMode{$Version} = 1;
8203 $Detected = "$1$2$3" if(not defined $Detected);
8204 }
8205 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8206 { # MATCH:
8207 # int operator(...);
8208 # DO NOT MATCH:
8209 # int operator()(...);
8210 $CppMode{$Version} = 1;
8211 $Detected = "$1$2$3" if(not defined $Detected);
8212 }
8213 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8214 { # MATCH:
8215 # int foo(int operator);
8216 # int foo(int operator, int other);
8217 # DO NOT MATCH:
8218 # int operator,(...);
8219 $CppMode{$Version} = 1;
8220 $Detected = "$1$2$3" if(not defined $Detected);
8221 }
8222 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8223 { # MATCH:
8224 # int foo(gboolean *bool);
8225 # DO NOT MATCH:
8226 # void setTabEnabled(int index, bool);
8227 $CppMode{$Version} = 1;
8228 $Detected = "$1$2$3" if(not defined $Detected);
8229 }
8230 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8231 { # MATCH:
8232 # int foo(int* this);
8233 # int bar(int this);
8234 # int baz(int throw);
8235 # DO NOT MATCH:
8236 # foo(X, this);
8237 $CppMode{$Version} = 1;
8238 $Detected = "$1$2$3$4" if(not defined $Detected);
8239 }
8240 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8241 { # MATCH:
8242 # struct template {...};
8243 # extern template foo(...);
8244 $CppMode{$Version} = 1;
8245 $Detected = "$1$2" if(not defined $Detected);
8246 }
8247
8248 if($CppMode{$Version} == 1)
8249 {
8250 if($Debug)
8251 {
8252 $Detected=~s/\A\s+//g;
8253 printMsg("INFO", "Detected code: \"$Detected\"");
8254 }
8255 }
8256
8257 # remove typedef enum NAME NAME;
8258 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8259 my $N = 0;
8260 while($N<=$#FwdTypedefs-1)
8261 {
8262 my $S = $FwdTypedefs[$N];
8263 if($S eq $FwdTypedefs[$N+1])
8264 {
8265 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008266 $CppMode{$Version} = 1;
8267
8268 if($Debug) {
8269 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8270 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008271 }
8272 $N+=2;
8273 }
8274
8275 if($CppMode{$Version}==1) {
8276 printMsg("INFO", "Using C++ compatibility mode");
8277 }
8278 }
8279
8280 if($CppMode{$Version}==1
8281 or $MinGWMode{$Version}==1)
8282 {
8283 my $IPath = $TMP_DIR."/dump$Version.i";
8284 writeFile($IPath, $Content);
8285 return $IPath;
8286 }
8287
8288 return undef;
8289}
8290
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008291sub getDump()
8292{
8293 if(not $GCC_PATH) {
8294 exitStatus("Error", "internal error - GCC path is not set");
8295 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008296
8297 my @Headers = keys(%{$Registered_Headers{$Version}});
8298 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8299
8300 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8301
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008302 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008303 my $HeaderPath = $TmpHeaderPath;
8304
8305 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008306 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008307 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8308 {
8309 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008310 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008311 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008312 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008313 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8314 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008315 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008316 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008317 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008318 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8319 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8320 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008321 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008322 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008323
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008324 if($ExtraInfo)
8325 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008326 if($IncludeString) {
8327 writeFile($ExtraInfo."/include-string", $IncludeString);
8328 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008329 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8330 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008331
8332 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8333 {
8334 my $REDIR = "";
8335 foreach my $P1 (sort @Redirects) {
8336 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8337 }
8338 writeFile($ExtraInfo."/include-redirect", $REDIR);
8339 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008340 }
8341
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008342 if(not keys(%{$TargetHeaders{$Version}}))
8343 { # Target headers
8344 addTargetHeaders($Version);
8345 }
8346
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008347 # clean memory
8348 %RecursiveIncludes = ();
8349 %Header_Include_Prefix = ();
8350 %Header_Includes = ();
8351
8352 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008353 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008354 delete($Cache{"detect_header_includes"});
8355 delete($Cache{"selectSystemHeader"});
8356
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008357 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008358 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8359 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008360
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008361 if($ExtraInfo)
8362 { # extra information for other tools
8363 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8364 }
8365
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008366 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008367 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008368 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008369
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008370 if($COMMON_LANGUAGE{$Version} eq "C++") {
8371 checkCTags($Pre);
8372 }
8373
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008374 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8375 { # try to correct the preprocessor output
8376 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008377 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008378
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008379 if($COMMON_LANGUAGE{$Version} eq "C++")
8380 { # add classes and namespaces to the dump
8381 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008382 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008383 or $MinGWMode{$Version}==1) {
8384 $CHdump .= " -fpreprocessed";
8385 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008386 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008387 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008388 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008389 chdir($ORIG_DIR);
8390 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8391 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008392 my $Content = readFile($ClassDump);
8393 foreach my $ClassInfo (split(/\n\n/, $Content))
8394 {
8395 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8396 {
8397 my $CName = $1;
8398 next if($CName=~/\A(__|_objc_|_opaque_)/);
8399 $TUnit_NameSpaces{$Version}{$CName} = -1;
8400 if($CName=~/\A[\w:]+\Z/)
8401 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008402 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008403 }
8404 if($CName=~/(\w[\w:]*)::/)
8405 { # namespaces
8406 my $NS = $1;
8407 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8408 $TUnit_NameSpaces{$Version}{$NS} = 1;
8409 }
8410 }
8411 }
8412 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8413 { # read v-tables (advanced approach)
8414 my ($CName, $VTable) = ($1, $2);
8415 $ClassVTable_Content{$Version}{$CName} = $VTable;
8416 }
8417 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008418 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8419 { # add user-defined namespaces
8420 $TUnit_NameSpaces{$Version}{$NS} = 1;
8421 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008422 if($Debug)
8423 { # debug mode
8424 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008425 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008426 }
8427 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008428 }
8429
8430 # add namespaces and classes
8431 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8432 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008433 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008434 }
8435 # some GCC versions don't include class methods to the TU dump by default
8436 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008437 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008438 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8439 {
8440 next if($C_Structure{$CName});
8441 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008442 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008443 if(not $Force and $GCC_44
8444 and $OSgroup eq "linux")
8445 { # optimization for linux with GCC >= 4.4
8446 # disable this code by -force option
8447 if(index($CName, "::")!=-1)
8448 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008449 next;
8450 }
8451 }
8452 else
8453 {
8454 if($CName=~/\A(.+)::[^:]+\Z/
8455 and $TUnit_Classes{$Version}{$1})
8456 { # classes inside other classes
8457 next;
8458 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008459 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008460 if(defined $TUnit_Funcs{$Version}{$CName})
8461 { # the same name for a function and type
8462 next;
8463 }
8464 if(defined $TUnit_Vars{$Version}{$CName})
8465 { # the same name for a variable and type
8466 next;
8467 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008468 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8469 }
8470 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008471 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008472 }
8473 }
8474 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8475 # create TU dump
8476 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008477 if($UserLang eq "C") {
8478 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8479 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008480 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008481 or $MinGWMode{$Version}==1) {
8482 $TUdump .= " -fpreprocessed";
8483 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008484 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008485 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8486 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008487 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008488 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008489 if($?)
8490 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008491 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008492 { # try to recompile
8493 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008494 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008495 and index($Errors, "c99_")!=-1
8496 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008497 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008498 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008499
8500 if($Debug)
8501 {
8502 # printMsg("INFO", $Errors);
8503 }
8504
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008505 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008506 resetLogging($Version);
8507 $TMP_DIR = tempdir(CLEANUP=>1);
8508 return getDump();
8509 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008510 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008511 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008512 { # add auto preamble headers and try again
8513 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008514 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008515 foreach my $Num (0 .. $#Headers)
8516 {
8517 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008518 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8519 {
8520 push_U($Include_Preamble{$Version}, $Path);
8521 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008522 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008523 }
8524 resetLogging($Version);
8525 $TMP_DIR = tempdir(CLEANUP=>1);
8526 return getDump();
8527 }
8528 elsif($Cpp0xMode{$Version}!=-1
8529 and ($Errors=~/\Q-std=c++0x\E/
8530 or $Errors=~/is not a class or namespace/))
8531 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008532 if(check_gcc($GCC_PATH, "4.6"))
8533 {
8534 $Cpp0xMode{$Version}=-1;
8535 printMsg("INFO", "Enabling c++0x mode");
8536 resetLogging($Version);
8537 $TMP_DIR = tempdir(CLEANUP=>1);
8538 $CompilerOptions{$Version} .= " -std=c++0x";
8539 return getDump();
8540 }
8541 else {
8542 printMsg("WARNING", "Probably c++0x construction detected");
8543 }
8544
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008545 }
8546 elsif($MinGWMode{$Version}==1)
8547 { # disable MinGW mode and try again
8548 $MinGWMode{$Version}=-1;
8549 resetLogging($Version);
8550 $TMP_DIR = tempdir(CLEANUP=>1);
8551 return getDump();
8552 }
8553 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008554 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008555 else {
8556 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008557 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008558 printMsg("ERROR", "some errors occurred when compiling headers");
8559 printErrorLog($Version);
8560 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008561 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008562 }
8563 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008564 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008565 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008566
8567 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8568 return $TUs[0];
8569 }
8570 else
8571 {
8572 my $Msg = "can't compile header(s)";
8573 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8574 $Msg .= "\nDid you install G++?";
8575 }
8576 exitStatus("Cannot_Compile", $Msg);
8577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008578}
8579
8580sub cmd_file($)
8581{
8582 my $Path = $_[0];
8583 return "" if(not $Path or not -e $Path);
8584 if(my $CmdPath = get_CmdPath("file")) {
8585 return `$CmdPath -b \"$Path\"`;
8586 }
8587 return "";
8588}
8589
8590sub getIncString($$)
8591{
8592 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008593 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008594 my $String = "";
8595 foreach (@{$ArrRef}) {
8596 $String .= " ".inc_opt($_, $Style);
8597 }
8598 return $String;
8599}
8600
8601sub getIncPaths(@)
8602{
8603 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008604 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008605 if($INC_PATH_AUTODETECT{$Version})
8606 { # auto-detecting dependencies
8607 my %Includes = ();
8608 foreach my $HPath (@HeaderPaths)
8609 {
8610 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8611 {
8612 if($Skip_Include_Paths{$Version}{$Dir}) {
8613 next;
8614 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008615 if($SystemRoot)
8616 {
8617 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8618 next;
8619 }
8620 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008621 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008622 }
8623 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008624 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008625 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008626 }
8627 }
8628 else
8629 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008630 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008631 }
8632 return \@IncPaths;
8633}
8634
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008635sub push_U($@)
8636{ # push unique
8637 if(my $Array = shift @_)
8638 {
8639 if(@_)
8640 {
8641 my %Exist = map {$_=>1} @{$Array};
8642 foreach my $Elem (@_)
8643 {
8644 if(not defined $Exist{$Elem})
8645 {
8646 push(@{$Array}, $Elem);
8647 $Exist{$Elem} = 1;
8648 }
8649 }
8650 }
8651 }
8652}
8653
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008654sub callPreprocessor($$$)
8655{
8656 my ($Path, $Inc, $LibVersion) = @_;
8657 return "" if(not $Path or not -f $Path);
8658 my $IncludeString=$Inc;
8659 if(not $Inc) {
8660 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8661 }
8662 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008663 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008664 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008665 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008666}
8667
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008668sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008669{ # native "find" is much faster than File::Find (~6x)
8670 # also the File::Find doesn't support --maxdepth N option
8671 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008672 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008673 return () if(not $Path or not -e $Path);
8674 if($OSgroup eq "windows")
8675 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008676 $Path = get_abs_path($Path);
8677 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008678 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008679 if($MaxDepth!=1) {
8680 $Cmd .= " /S";
8681 }
8682 if($Type eq "d") {
8683 $Cmd .= " /AD";
8684 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008685 elsif($Type eq "f") {
8686 $Cmd .= " /A-D";
8687 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008688 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008689 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008690 {
8691 if(not $UseRegex)
8692 { # FIXME: how to search file names in MS shell?
8693 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008694 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008695 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008696 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008697 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008698 }
8699 my @AbsPaths = ();
8700 foreach my $File (@Files)
8701 {
8702 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008703 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008704 }
8705 if($Type eq "f" and not -f $File)
8706 { # skip dirs
8707 next;
8708 }
8709 push(@AbsPaths, path_format($File, $OSgroup));
8710 }
8711 if($Type eq "d") {
8712 push(@AbsPaths, $Path);
8713 }
8714 return @AbsPaths;
8715 }
8716 else
8717 {
8718 my $FindCmd = get_CmdPath("find");
8719 if(not $FindCmd) {
8720 exitStatus("Not_Found", "can't find a \"find\" command");
8721 }
8722 $Path = get_abs_path($Path);
8723 if(-d $Path and -l $Path
8724 and $Path!~/\/\Z/)
8725 { # for directories that are symlinks
8726 $Path.="/";
8727 }
8728 my $Cmd = $FindCmd." \"$Path\"";
8729 if($MaxDepth) {
8730 $Cmd .= " -maxdepth $MaxDepth";
8731 }
8732 if($Type) {
8733 $Cmd .= " -type $Type";
8734 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008735 if($Name and not $UseRegex)
8736 { # wildcards
8737 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008738 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008739 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008740 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008741 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8742 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008743 my @Files = split(/\n/, $Res);
8744 if($Name and $UseRegex)
8745 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008746 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008747 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008748 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008749 }
8750}
8751
8752sub unpackDump($)
8753{
8754 my $Path = $_[0];
8755 return "" if(not $Path or not -e $Path);
8756 $Path = get_abs_path($Path);
8757 $Path = path_format($Path, $OSgroup);
8758 my ($Dir, $FileName) = separate_path($Path);
8759 my $UnpackDir = $TMP_DIR."/unpack";
8760 rmtree($UnpackDir);
8761 mkpath($UnpackDir);
8762 if($FileName=~s/\Q.zip\E\Z//g)
8763 { # *.zip
8764 my $UnzipCmd = get_CmdPath("unzip");
8765 if(not $UnzipCmd) {
8766 exitStatus("Not_Found", "can't find \"unzip\" command");
8767 }
8768 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008769 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008770 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008771 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008772 }
8773 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008774 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008775 if(not @Contents) {
8776 exitStatus("Error", "can't extract \'$Path\'");
8777 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008778 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008779 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008780 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008781 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008782 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008783 if($OSgroup eq "windows")
8784 { # -xvzf option is not implemented in tar.exe (2003)
8785 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8786 my $TarCmd = get_CmdPath("tar");
8787 if(not $TarCmd) {
8788 exitStatus("Not_Found", "can't find \"tar\" command");
8789 }
8790 my $GzipCmd = get_CmdPath("gzip");
8791 if(not $GzipCmd) {
8792 exitStatus("Not_Found", "can't find \"gzip\" command");
8793 }
8794 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008795 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008796 if($?) {
8797 exitStatus("Error", "can't extract \'$Path\'");
8798 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008799 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008800 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008801 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008802 }
8803 chdir($ORIG_DIR);
8804 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008805 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008806 if(not @Contents) {
8807 exitStatus("Error", "can't extract \'$Path\'");
8808 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008809 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008810 }
8811 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008812 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008813 my $TarCmd = get_CmdPath("tar");
8814 if(not $TarCmd) {
8815 exitStatus("Not_Found", "can't find \"tar\" command");
8816 }
8817 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008818 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008819 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008820 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008821 }
8822 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008823 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008824 if(not @Contents) {
8825 exitStatus("Error", "can't extract \'$Path\'");
8826 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008827 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008828 }
8829 }
8830}
8831
8832sub createArchive($$)
8833{
8834 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008835 if(not $To) {
8836 $To = ".";
8837 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008838 if(not $Path or not -e $Path
8839 or not -d $To) {
8840 return "";
8841 }
8842 my ($From, $Name) = separate_path($Path);
8843 if($OSgroup eq "windows")
8844 { # *.zip
8845 my $ZipCmd = get_CmdPath("zip");
8846 if(not $ZipCmd) {
8847 exitStatus("Not_Found", "can't find \"zip\"");
8848 }
8849 my $Pkg = $To."/".$Name.".zip";
8850 unlink($Pkg);
8851 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008852 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008853 if($?)
8854 { # cannot allocate memory (or other problems with "zip")
8855 unlink($Path);
8856 exitStatus("Error", "can't pack the ABI dump: ".$!);
8857 }
8858 chdir($ORIG_DIR);
8859 unlink($Path);
8860 return $Pkg;
8861 }
8862 else
8863 { # *.tar.gz
8864 my $TarCmd = get_CmdPath("tar");
8865 if(not $TarCmd) {
8866 exitStatus("Not_Found", "can't find \"tar\"");
8867 }
8868 my $GzipCmd = get_CmdPath("gzip");
8869 if(not $GzipCmd) {
8870 exitStatus("Not_Found", "can't find \"gzip\"");
8871 }
8872 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8873 unlink($Pkg);
8874 chdir($From);
8875 system($TarCmd, "-czf", $Pkg, $Name);
8876 if($?)
8877 { # cannot allocate memory (or other problems with "tar")
8878 unlink($Path);
8879 exitStatus("Error", "can't pack the ABI dump: ".$!);
8880 }
8881 chdir($ORIG_DIR);
8882 unlink($Path);
8883 return $To."/".$Name.".tar.gz";
8884 }
8885}
8886
8887sub is_header_file($)
8888{
8889 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8890 return $_[0];
8891 }
8892 return 0;
8893}
8894
8895sub is_not_header($)
8896{
8897 if($_[0]=~/\.\w+\Z/
8898 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8899 return 1;
8900 }
8901 return 0;
8902}
8903
8904sub is_header($$$)
8905{
8906 my ($Header, $UserDefined, $LibVersion) = @_;
8907 return 0 if(-d $Header);
8908 if(-f $Header) {
8909 $Header = get_abs_path($Header);
8910 }
8911 else
8912 {
8913 if(is_abs($Header))
8914 { # incorrect absolute path
8915 return 0;
8916 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008917 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008918 $Header = $HPath;
8919 }
8920 else
8921 { # can't find header
8922 return 0;
8923 }
8924 }
8925 if($Header=~/\.\w+\Z/)
8926 { # have an extension
8927 return is_header_file($Header);
8928 }
8929 else
8930 {
8931 if($UserDefined==2)
8932 { # specified on the command line
8933 if(cmd_file($Header)!~/HTML|XML/i) {
8934 return $Header;
8935 }
8936 }
8937 elsif($UserDefined)
8938 { # specified in the XML-descriptor
8939 # header file without an extension
8940 return $Header;
8941 }
8942 else
8943 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008944 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008945 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008946 { # !~/HTML|XML|shared|dynamic/i
8947 return $Header;
8948 }
8949 }
8950 }
8951 return 0;
8952}
8953
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008954sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008955{
8956 my $LibVersion = $_[0];
8957 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8958 {
8959 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008960 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008961
8962 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
8963 detect_recursive_includes($RegHeader, $LibVersion);
8964 }
8965
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008966 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
8967 {
8968 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008969
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04008970 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008971 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
8972 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008973 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008974 }
8975 }
8976 }
8977}
8978
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008979sub familiarDirs($$)
8980{
8981 my ($D1, $D2) = @_;
8982 if($D1 eq $D2) {
8983 return 1;
8984 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04008985
8986 my $U1 = index($D1, "/usr/");
8987 my $U2 = index($D2, "/usr/");
8988
8989 if($U1==0 and $U2!=0) {
8990 return 0;
8991 }
8992
8993 if($U2==0 and $U1!=0) {
8994 return 0;
8995 }
8996
8997 if(index($D2, $D1."/")==0) {
8998 return 1;
8999 }
9000
9001 # /usr/include/DIR
9002 # /home/user/DIR
9003
9004 my $DL = get_depth($D1);
9005
9006 my @Dirs1 = ($D1);
9007 while($DL - get_depth($D1)<=2
9008 and get_depth($D1)>=4
9009 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9010 push(@Dirs1, $D1);
9011 }
9012
9013 my @Dirs2 = ($D2);
9014 while(get_depth($D2)>=4
9015 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9016 push(@Dirs2, $D2);
9017 }
9018
9019 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009020 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009021 foreach my $P2 (@Dirs2)
9022 {
9023
9024 if($P1 eq $P2) {
9025 return 1;
9026 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009027 }
9028 }
9029 return 0;
9030}
9031
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009032sub readHeaders($)
9033{
9034 $Version = $_[0];
9035 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9036 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009037 if($Debug)
9038 { # debug mode
9039 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009040 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009041 }
9042 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009043}
9044
9045sub prepareTypes($)
9046{
9047 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009048 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009049 { # support for old ABI dumps
9050 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009051 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009052 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009053 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9054 if($TName=~/\A(\w+)::(\w+)/) {
9055 my ($P1, $P2) = ($1, $2);
9056 if($P1 eq $P2) {
9057 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009058 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009059 else {
9060 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9061 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009062 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009063 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009064 }
9065 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009066 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009067 { # support for old ABI dumps
9068 # V < 2.5: array size == "number of elements"
9069 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009070 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009071 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009072 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009073 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009074 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009075 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009076 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009077 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009078 $Size *= $Base{"Size"};
9079 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009080 }
9081 else
9082 { # array[] is a pointer
9083 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009084 }
9085 }
9086 }
9087 }
9088 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009089 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009090 { # support for old ABI dumps
9091 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009092 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009093 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009094 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009095 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009096 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009097 my %Type = get_Type($TypeId, $LibVersion);
9098 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9099 my %Type2 = get_Type($TypeId_2, $V2);
9100 if($Type{"Size"} ne $Type2{"Size"}) {
9101 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009102 }
9103 }
9104 }
9105 }
9106}
9107
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009108sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009109{
9110 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009111
9112 if(not keys(%{$SymbolInfo{$LibVersion}}))
9113 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009114 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009115 {
9116 if($CheckHeadersOnly) {
9117 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9118 }
9119 else {
9120 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9121 }
9122 }
9123 }
9124
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009125 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009126 if(not checkDump(1, "2.10")
9127 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009128 { # different formats
9129 $Remangle = 1;
9130 }
9131 if($CheckHeadersOnly)
9132 { # different languages
9133 if($UserLang)
9134 { # --lang=LANG for both versions
9135 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9136 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9137 {
9138 if($UserLang eq "C++")
9139 { # remangle symbols
9140 $Remangle = 1;
9141 }
9142 elsif($UserLang eq "C")
9143 { # remove mangling
9144 $Remangle = -1;
9145 }
9146 }
9147 }
9148 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009149
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009150 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009151 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009152 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009153 { # support for old ABI dumps
9154 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9155 {
9156 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9157 {
9158 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9159 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009160 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009161 if(defined $DVal and $DVal ne "")
9162 {
9163 if($TName eq "char") {
9164 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9165 }
9166 elsif($TName eq "bool") {
9167 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9168 }
9169 }
9170 }
9171 }
9172 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009173 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009174 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009175 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9176 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009177 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009178 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9179 # + support for old ABI dumps
9180 next;
9181 }
9182 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009183 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009184 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009185 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009186 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009187
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009188 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009189 if(not checkDump(1, "2.12")
9190 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009191 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009192 if($ShortName eq "operator>>")
9193 {
9194 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9195 { # corrected mangling of operator>>
9196 $SRemangle = 1;
9197 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009198 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009199 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9200 {
9201 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9202 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9203 { # corrected mangling of const global data
9204 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9205 # and incorrectly mangled by old ACC versions
9206 $SRemangle = 1;
9207 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009208 }
9209 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009210 if(not $CheckHeadersOnly)
9211 { # support for old ABI dumps
9212 if(not checkDump(1, "2.17")
9213 or not checkDump(2, "2.17"))
9214 {
9215 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9216 {
9217 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9218 {
9219 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9220 {
9221 $MnglName = $ShortName;
9222 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9223 }
9224 }
9225 }
9226 }
9227 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009228 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009229 { # support for old ABI dumps: some symbols are not mangled in old dumps
9230 # mangle both sets of symbols (old and new)
9231 # NOTE: remangling all symbols by the same mangler
9232 if($MnglName=~/\A_ZN(V|)K/)
9233 { # mangling may be incorrect on old ABI dumps
9234 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009235 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009236 }
9237 if($MnglName=~/\A_ZN(K|)V/)
9238 { # mangling may be incorrect on old ABI dumps
9239 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009240 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009241 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009242 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9243 or (not $ClassID and $CheckHeadersOnly)
9244 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9245 { # support for old ABI dumps, GCC >= 4.0
9246 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009247 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009248 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009249 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009250 $MangledNames{$LibVersion}{$MnglName} = 1;
9251 }
9252 }
9253 }
9254 elsif($Remangle==-1)
9255 { # remove mangling
9256 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009257 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009259 if(not $MnglName) {
9260 next;
9261 }
9262 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9263 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009264 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9265
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009266 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009267 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009268 { # support for old dumps
9269 # add "Volatile" attribute
9270 if($MnglName=~/_Z(K|)V/) {
9271 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9272 }
9273 }
9274 # symbol and its symlink have same signatures
9275 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009276 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009277 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009278
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009279 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9280 {
9281 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9282 if($SymVer{$LibVersion}{$Alias}) {
9283 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9284 }
9285 }
9286
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009287 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009288 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009289 }
9290 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9291 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9292 }
9293 if($ExtendedCheck)
9294 { # --ext option
9295 addExtension($LibVersion);
9296 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009297
9298 # clean memory
9299 delete($SymbolInfo{$LibVersion});
9300
9301 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009302 { # detect allocable classes with public exported constructors
9303 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009304 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009305 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009306 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009307 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009308 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9309 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009310 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009311 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009312 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009313 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009314 $AllocableClass{$LibVersion}{$ClassName} = 1;
9315 }
9316 }
9317 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009318 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009319 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009320 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009321 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009322 if($CheckHeadersOnly)
9323 {
9324 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9325 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9326 { # all symbols except non-virtual inline
9327 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9328 }
9329 }
9330 else {
9331 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009332 }
9333 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009334 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009335 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009336 }
9337 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009338 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009339 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009340 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009341 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009342 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009343 if(defined $Base{"Type"}
9344 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009345 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009346 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009347 if($Name=~/<([^<>\s]+)>/)
9348 {
9349 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9350 $ReturnedClass{$LibVersion}{$Tid} = 1;
9351 }
9352 }
9353 else {
9354 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9355 }
9356 }
9357 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009358 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009359 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009360 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009361 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009362 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009363 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009364 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009365 if($Base{"Type"}=~/Struct|Class/)
9366 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009367 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009368 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9369 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009370 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009372 }
9373 }
9374 }
9375 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009376
9377 # mapping {short name => symbols}
9378 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009379 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009380 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009381 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009382 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009383 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009384 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009385 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009386 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9387 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009388 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009389 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009390 }
9391 }
9392 }
9393 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009394
9395 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009396 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009397 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009398 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009399 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009400 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9401 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009402 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009403 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009404 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009405 $ClassNames{$LibVersion}{$TName} = 1;
9406 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009407 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009408 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9409 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009410 }
9411 }
9412 }
9413 }
9414 }
9415}
9416
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009417sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009418{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009419 my ($Tid, $LibVersion) = @_;
9420 if(not $Tid) {
9421 return $Tid;
9422 }
9423
9424 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9425 {
9426 if($TName_Tid{$LibVersion}{$Name}) {
9427 return $TName_Tid{$LibVersion}{$Name};
9428 }
9429 }
9430
9431 return $Tid;
9432}
9433
9434sub register_SymbolUsage($$$)
9435{
9436 my ($InfoId, $UsedType, $LibVersion) = @_;
9437
9438 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9439 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9440 {
9441 register_TypeUsage($RTid, $UsedType, $LibVersion);
9442 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9443 }
9444 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9445 {
9446 register_TypeUsage($FCid, $UsedType, $LibVersion);
9447 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9448
9449 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9450 { # register "this" pointer
9451 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9452 }
9453 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9454 { # register "this" pointer (const method)
9455 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9456 }
9457 }
9458 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9459 {
9460 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9461 {
9462 register_TypeUsage($PTid, $UsedType, $LibVersion);
9463 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9464 }
9465 }
9466 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9467 {
9468 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9469 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9470 register_TypeUsage($TTid, $UsedType, $LibVersion);
9471 }
9472 }
9473}
9474
9475sub register_TypeUsage($$$)
9476{
9477 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009478 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009479 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009480 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009481 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009482 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009483 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009484 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009485
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009486 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009487 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009488 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009489 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009490 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009491 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9492 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9493 }
9494 }
9495
9496 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9497 {
9498 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009499 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009500 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009501 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9502 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009503 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009504 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9505 {
9506 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9507 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009508 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009509 }
9510 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009511 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009512 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009513 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009514 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9515 {
9516 register_TypeUsage($MTid, $UsedType, $LibVersion);
9517 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009518 }
9519 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009520 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009521 or $TInfo{"Type"} eq "MethodPtr"
9522 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009523 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009524 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009525 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009526 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009527 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009528 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009529 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9530 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009531 }
9532 }
9533 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009534 if($TInfo{"Type"} eq "FieldPtr")
9535 {
9536 if(my $RTid = $TInfo{"Return"}) {
9537 register_TypeUsage($RTid, $UsedType, $LibVersion);
9538 }
9539 if(my $CTid = $TInfo{"Class"}) {
9540 register_TypeUsage($CTid, $UsedType, $LibVersion);
9541 }
9542 }
9543 if($TInfo{"Type"} eq "MethodPtr")
9544 {
9545 if(my $CTid = $TInfo{"Class"}) {
9546 register_TypeUsage($CTid, $UsedType, $LibVersion);
9547 }
9548 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009549 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009550 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009551 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009552 $UsedType->{$TypeId} = 1;
9553 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9554 {
9555 register_TypeUsage($BTid, $UsedType, $LibVersion);
9556 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9557 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009558 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009559 else
9560 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9561 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009562 }
9563 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009564}
9565
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009566sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009567{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009568 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9569
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009570 if($Level eq "Dump")
9571 {
9572 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9573 { # TODO: check if this symbol is from
9574 # base classes of other target symbols
9575 return 1;
9576 }
9577 }
9578
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009579 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9580 { # stdc++ interfaces
9581 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009582 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009583
9584 my $Target = 0;
9585 if(my $Header = $SInfo->{"Header"}) {
9586 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9587 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009588 if($ExtendedCheck)
9589 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009590 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009591 $Target = 1;
9592 }
9593 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009594 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009595 {
9596 if($Target)
9597 {
9598 if($Level eq "Dump")
9599 { # dumped
9600 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009601 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009602 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009603 return 1;
9604 }
9605 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009606 else {
9607 return 1;
9608 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009609 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009610 elsif($Level eq "Source")
9611 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009612 return 1;
9613 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009614 elsif($Level eq "Binary")
9615 { # checked
9616 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9617 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9618 return 1;
9619 }
9620 }
9621 }
9622 }
9623 else
9624 { # library is available
9625 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9626 { # exported symbols
9627 return 1;
9628 }
9629 if($Level eq "Dump")
9630 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009631 if($BinaryOnly)
9632 {
9633 if($SInfo->{"Data"})
9634 {
9635 if($Target) {
9636 return 1;
9637 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009638 }
9639 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009640 else
9641 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009642 if($Target) {
9643 return 1;
9644 }
9645 }
9646 }
9647 elsif($Level eq "Source")
9648 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009649 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009650 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009651 { # skip LOCAL symbols
9652 if($Target) {
9653 return 1;
9654 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009655 }
9656 }
9657 elsif($Level eq "Binary")
9658 { # checked
9659 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9660 {
9661 if($Target) {
9662 return 1;
9663 }
9664 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009665 }
9666 }
9667 return 0;
9668}
9669
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009670sub cleanDump($)
9671{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009672 my $LibVersion = $_[0];
9673 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9674 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009675 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9676 {
9677 delete($SymbolInfo{$LibVersion}{$InfoId});
9678 next;
9679 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009680 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009681 if(not $MnglName)
9682 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009683 delete($SymbolInfo{$LibVersion}{$InfoId});
9684 next;
9685 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009686 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009687 if(not $ShortName)
9688 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009689 delete($SymbolInfo{$LibVersion}{$InfoId});
9690 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009691 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009692 if($MnglName eq $ShortName)
9693 { # remove duplicate data
9694 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009695 }
9696 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9697 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9698 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009699 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9700 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9701 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009702 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009703 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009704 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009705 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009706 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9707 {
9708 delete($TypeInfo{$LibVersion}{$Tid});
9709 next;
9710 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009711 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009712 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009713 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009714 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9715 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9716 }
9717 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009718 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9719 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9720 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009721 }
9722}
9723
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009724sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009725{
9726 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009727
9728 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9729 {
9730 if(defined $TypeInfo{$LibVersion}{$Dupl})
9731 {
9732 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9733 { # duplicate
9734 return 0;
9735 }
9736 }
9737 }
9738
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009739 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9740
9741 if(isBuiltIn($THeader)) {
9742 return 0;
9743 }
9744
9745 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9746 return 0;
9747 }
9748
9749 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9750 return 0;
9751 }
9752
9753 if(selfTypedef($Tid, $LibVersion)) {
9754 return 0;
9755 }
9756
9757 if(not isTargetType($Tid, $LibVersion)) {
9758 return 0;
9759 }
9760
9761 return 0;
9762}
9763
9764sub isTargetType($$)
9765{
9766 my ($Tid, $LibVersion) = @_;
9767
9768 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9769 { # derived
9770 return 1;
9771 }
9772
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009773 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9774 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009775 if(not is_target_header($THeader, $LibVersion))
9776 { # from target headers
9777 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009778 }
9779 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009780
9781 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009782}
9783
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009784sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009785{ # remove unused data types from the ABI dump
9786 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009787
9788 my %UsedType = ();
9789
9790 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009791 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009792 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009793 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009794 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009795 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009796 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009797 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009798 next;
9799 }
9800
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009801 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009802 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009803 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009804 {
9805 my %Tree = ();
9806 register_TypeUsage($Tid, \%Tree, $LibVersion);
9807
9808 my $Tmpl = 0;
9809 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9810 {
9811 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9812 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9813 {
9814 $Tmpl = 1;
9815 last;
9816 }
9817 }
9818 if(not $Tmpl)
9819 {
9820 foreach (keys(%Tree)) {
9821 $UsedType{$_} = 1;
9822 }
9823 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009824 }
9825 }
9826 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009827
9828 my %Delete = ();
9829
9830 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009831 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009832 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009833 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009834 next;
9835 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009836
9837 if($Kind eq "Extra")
9838 {
9839 my %Tree = ();
9840 register_TypeUsage($Tid, \%Tree, $LibVersion);
9841
9842 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9843 {
9844 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9845 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9846 {
9847 $Delete{$Tid} = 1;
9848 last;
9849 }
9850 }
9851 }
9852 else
9853 {
9854 # remove type
9855 delete($TypeInfo{$LibVersion}{$Tid});
9856 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009857 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009858
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009859 if($Kind eq "Extra")
9860 { # remove duplicates
9861 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9862 {
9863 if($UsedType{$Tid})
9864 { # All & Extended
9865 next;
9866 }
9867
9868 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9869
9870 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9871 delete($TypeInfo{$LibVersion}{$Tid});
9872 }
9873 }
9874 }
9875
9876 foreach my $Tid (keys(%Delete))
9877 {
9878 delete($TypeInfo{$LibVersion}{$Tid});
9879 }
9880}
9881
9882sub check_Completeness($$)
9883{
9884 my ($Info, $LibVersion) = @_;
9885
9886 # data types
9887 if(defined $Info->{"Memb"})
9888 {
9889 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9890 {
9891 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9892 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9893 }
9894 }
9895 }
9896 if(defined $Info->{"Base"})
9897 {
9898 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9899 check_TypeInfo($Bid, $LibVersion);
9900 }
9901 }
9902 if(defined $Info->{"BaseType"}) {
9903 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9904 }
9905 if(defined $Info->{"TParam"})
9906 {
9907 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9908 {
9909 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9910 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9911 next;
9912 }
9913 if($TName eq "_BoolType") {
9914 next;
9915 }
9916 if($TName=~/\Asizeof\(/) {
9917 next;
9918 }
9919 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9920 check_TypeInfo($Tid, $LibVersion);
9921 }
9922 else
9923 {
9924 if(defined $Debug) {
9925 printMsg("WARNING", "missed type $TName");
9926 }
9927 }
9928 }
9929 }
9930
9931 # symbols
9932 if(defined $Info->{"Param"})
9933 {
9934 foreach my $Pos (keys(%{$Info->{"Param"}}))
9935 {
9936 if(defined $Info->{"Param"}{$Pos}{"type"}) {
9937 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
9938 }
9939 }
9940 }
9941 if(defined $Info->{"Return"}) {
9942 check_TypeInfo($Info->{"Return"}, $LibVersion);
9943 }
9944 if(defined $Info->{"Class"}) {
9945 check_TypeInfo($Info->{"Class"}, $LibVersion);
9946 }
9947}
9948
9949sub check_TypeInfo($$)
9950{
9951 my ($Tid, $LibVersion) = @_;
9952
9953 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
9954 return;
9955 }
9956 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
9957
9958 if(defined $TypeInfo{$LibVersion}{$Tid})
9959 {
9960 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
9961 printMsg("ERROR", "missed type name ($Tid)");
9962 }
9963 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
9964 }
9965 else {
9966 printMsg("ERROR", "missed type id $Tid");
9967 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009968}
9969
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009970sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009971{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009972 my ($TypeId, $LibVersion) = @_;
9973 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009974 if($Type{"Type"} eq "Typedef")
9975 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009976 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009977 if($Base{"Type"}=~/Class|Struct/)
9978 {
9979 if($Type{"Name"} eq $Base{"Name"}) {
9980 return 1;
9981 }
9982 elsif($Type{"Name"}=~/::(\w+)\Z/)
9983 {
9984 if($Type{"Name"} eq $Base{"Name"}."::".$1)
9985 { # QPointer<QWidget>::QPointer
9986 return 1;
9987 }
9988 }
9989 }
9990 }
9991 return 0;
9992}
9993
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009994sub addExtension($)
9995{
9996 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009997 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009998 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009999 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010000 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010001 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10002 $TName=~s/\A(struct|union|class|enum) //;
10003 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010004
10005 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10006 "Header" => "extended.h",
10007 "ShortName" => $Symbol,
10008 "MnglName" => $Symbol,
10009 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10010 );
10011
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010012 $ExtendedSymbols{$Symbol} = 1;
10013 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10014 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010015 }
10016 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010017 $ExtendedSymbols{"external_func_0"} = 1;
10018 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10019 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010020}
10021
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010022sub findMethod($$$)
10023{
10024 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010025 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010026 {
10027 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10028 return $VirtMethodInClass;
10029 }
10030 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10031 return $VirtMethodInBaseClasses;
10032 }
10033 }
10034 return "";
10035}
10036
10037sub findMethod_Class($$$)
10038{
10039 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010040 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010041 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10042 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10043 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10044 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10045 { # search for interface with the same parameters suffix (overridden)
10046 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10047 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010048 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10049 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010050 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10051 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010052 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10053 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10054 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10055 return $Candidate;
10056 }
10057 }
10058 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010059 else
10060 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010061 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10062 return $Candidate;
10063 }
10064 }
10065 }
10066 }
10067 return "";
10068}
10069
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010070sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010071{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010072 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010073 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010074 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010075 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10076 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010077 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010078 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010079 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010080 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10081 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010082 { # pure virtual D2-destructors are marked as "virt" in the dump
10083 # virtual D2-destructors are NOT marked as "virt" in the dump
10084 # both destructors are not presented in the v-table
10085 next;
10086 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010087 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010088 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10089 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010090 }
10091}
10092
10093sub registerOverriding($)
10094{
10095 my $LibVersion = $_[0];
10096 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010097 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010098 foreach my $ClassName (@Classes)
10099 {
10100 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10101 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010102 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10103 { # pure virtuals
10104 next;
10105 }
10106 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10107 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010108 {
10109 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10110 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10111 { # both overridden virtual methods
10112 # and implemented pure virtual methods
10113 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10114 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10115 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10116 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010117 }
10118 }
10119 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10120 delete($VirtualTable{$LibVersion}{$ClassName});
10121 }
10122 }
10123}
10124
10125sub setVirtFuncPositions($)
10126{
10127 my $LibVersion = $_[0];
10128 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10129 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010130 my ($Num, $Rel) = (1, 0);
10131
10132 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010133 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010134 if($UsedDump{$LibVersion}{"DWARF"}) {
10135 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10136 }
10137 else {
10138 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10139 }
10140 foreach my $VirtFunc (@Funcs)
10141 {
10142 if($UsedDump{$LibVersion}{"DWARF"}) {
10143 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10144 }
10145 else {
10146 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10147 }
10148
10149 # set relative positions
10150 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10151 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10152 { # relative position excluding added and removed virtual functions
10153 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10154 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10155 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10156 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010157 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010158 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010159 }
10160 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010161 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010162 {
10163 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010164 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010165 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010166 }
10167 }
10168}
10169
10170sub get_sub_classes($$$)
10171{
10172 my ($ClassId, $LibVersion, $Recursive) = @_;
10173 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10174 my @Subs = ();
10175 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10176 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010177 if($Recursive)
10178 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010179 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10180 push(@Subs, $SubSubId);
10181 }
10182 }
10183 push(@Subs, $SubId);
10184 }
10185 return @Subs;
10186}
10187
10188sub get_base_classes($$$)
10189{
10190 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010191 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010192 return () if(not defined $ClassType{"Base"});
10193 my @Bases = ();
10194 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10195 keys(%{$ClassType{"Base"}}))
10196 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010197 if($Recursive)
10198 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010199 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10200 push(@Bases, $SubBaseId);
10201 }
10202 }
10203 push(@Bases, $BaseId);
10204 }
10205 return @Bases;
10206}
10207
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010208sub getVTable_Model($$)
10209{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010210 my ($ClassId, $LibVersion) = @_;
10211 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10212 my @Elements = ();
10213 foreach my $BaseId (@Bases, $ClassId)
10214 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010215 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010216 {
10217 if(defined $VirtualTable{$LibVersion}{$BName})
10218 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010219 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10220 if($UsedDump{$LibVersion}{"DWARF"}) {
10221 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10222 }
10223 else {
10224 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10225 }
10226 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010227 push(@Elements, $VFunc);
10228 }
10229 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010230 }
10231 }
10232 return @Elements;
10233}
10234
10235sub getVShift($$)
10236{
10237 my ($ClassId, $LibVersion) = @_;
10238 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10239 my $VShift = 0;
10240 foreach my $BaseId (@Bases)
10241 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010242 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010243 {
10244 if(defined $VirtualTable{$LibVersion}{$BName}) {
10245 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010247 }
10248 }
10249 return $VShift;
10250}
10251
10252sub getShift($$)
10253{
10254 my ($ClassId, $LibVersion) = @_;
10255 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10256 my $Shift = 0;
10257 foreach my $BaseId (@Bases)
10258 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010259 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010260 {
10261 if($Size!=1)
10262 { # not empty base class
10263 $Shift+=$Size;
10264 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010265 }
10266 }
10267 return $Shift;
10268}
10269
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010270sub getVTable_Size($$)
10271{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010272 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010273 my $Size = 0;
10274 # three approaches
10275 if(not $Size)
10276 { # real size
10277 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10278 $Size = keys(%VTable);
10279 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010280 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010281 if(not $Size)
10282 { # shared library symbol size
10283 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10284 $Size /= $WORD_SIZE{$LibVersion};
10285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010286 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010287 if(not $Size)
10288 { # model size
10289 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10290 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10291 }
10292 }
10293 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010294}
10295
10296sub isCopyingClass($$)
10297{
10298 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010299 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010300}
10301
10302sub isLeafClass($$)
10303{
10304 my ($ClassId, $LibVersion) = @_;
10305 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10306}
10307
10308sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010309{ # check structured type for public fields
10310 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010311}
10312
10313sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010314{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010315 my ($TypePtr, $Skip, $Start, $End) = @_;
10316 return 0 if(not $TypePtr);
10317 if($End==-1) {
10318 $End = keys(%{$TypePtr->{"Memb"}})-1;
10319 }
10320 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10321 {
10322 if($Skip and $Skip->{$MemPos})
10323 { # skip removed/added fields
10324 next;
10325 }
10326 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10327 {
10328 if(isPublic($TypePtr, $MemPos)) {
10329 return ($MemPos+1);
10330 }
10331 }
10332 }
10333 return 0;
10334}
10335
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010336sub isReserved($)
10337{ # reserved fields == private
10338 my $MName = $_[0];
10339 if($MName=~/reserved|padding|f_spare/i) {
10340 return 1;
10341 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010342 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010343 return 1;
10344 }
10345 if($MName=~/(pad\d+)/i) {
10346 return 1;
10347 }
10348 return 0;
10349}
10350
10351sub isPublic($$)
10352{
10353 my ($TypePtr, $FieldPos) = @_;
10354 return 0 if(not $TypePtr);
10355 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10356 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10357 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10358 { # by name in C language
10359 # FIXME: add other methods to detect private members
10360 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10361 if($MName=~/priv|abidata|parent_object/i)
10362 { # C-styled private data
10363 return 0;
10364 }
10365 if(lc($MName) eq "abi")
10366 { # ABI information/reserved field
10367 return 0;
10368 }
10369 if(isReserved($MName))
10370 { # reserved fields
10371 return 0;
10372 }
10373 return 1;
10374 }
10375 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10376 { # by access in C++ language
10377 return 1;
10378 }
10379 return 0;
10380}
10381
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010382sub getVTable_Real($$)
10383{
10384 my ($ClassName, $LibVersion) = @_;
10385 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10386 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010387 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010388 if(defined $Type{"VTable"}) {
10389 return %{$Type{"VTable"}};
10390 }
10391 }
10392 return ();
10393}
10394
10395sub cmpVTables($)
10396{
10397 my $ClassName = $_[0];
10398 my $Res = cmpVTables_Real($ClassName, 1);
10399 if($Res==-1) {
10400 $Res = cmpVTables_Model($ClassName);
10401 }
10402 return $Res;
10403}
10404
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010405sub cmpVTables_Model($)
10406{
10407 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010408 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010409 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010410 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010411 return 1;
10412 }
10413 }
10414 return 0;
10415}
10416
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010417sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010418{
10419 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010420 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10421 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010422 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010423 my %VTable_Old = getVTable_Real($ClassName, 1);
10424 my %VTable_New = getVTable_Real($ClassName, 2);
10425 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010426 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010427 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010428 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010429 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010430 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10431 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010432 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010433 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010434 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010435 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010436 my $Entry1 = $VTable_Old{$Offset};
10437 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010438 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010439 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010440 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010441 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010442
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010443 $Entry1 = simpleVEntry($Entry1);
10444 $Entry2 = simpleVEntry($Entry2);
10445 if($Entry1 ne $Entry2)
10446 { # register as changed
10447 if($Entry1=~/::([^:]+)\Z/)
10448 {
10449 my $M1 = $1;
10450 if($Entry2=~/::([^:]+)\Z/)
10451 {
10452 my $M2 = $1;
10453 if($M1 eq $M2)
10454 { # overridden
10455 next;
10456 }
10457 }
10458 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010459 if(differentDumps("G"))
10460 {
10461 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10462 {
10463 # GCC 4.6.1: -0x00000000000000010
10464 # GCC 4.7.0: -16
10465 next;
10466 }
10467 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010468 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010469 }
10470 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010471 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010472}
10473
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010474sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010475{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010476 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010477 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10478 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010479 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010480 { # already registered
10481 next;
10482 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010483 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010484 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010485 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010486 foreach my $Symbol (@Affected)
10487 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010488 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010489 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010490 "Target"=>$ClassName);
10491 }
10492 }
10493 }
10494}
10495
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010496sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010497{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010498 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010499 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010500 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010501 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010502 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010503 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010504 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010505 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010506 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010507 if($TName_Tid{1}{$ClassName}
10508 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010509 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010510 if(defined $CompleteSignature{1}{$Symbol}
10511 and $CompleteSignature{1}{$Symbol}{"Virt"})
10512 { # override some method in v.1
10513 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010514 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010515 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010516 }
10517 }
10518 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010519 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010520 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010521 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010522 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010523 if($TName_Tid{2}{$ClassName}
10524 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010525 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010526 if(defined $CompleteSignature{2}{$Symbol}
10527 and $CompleteSignature{2}{$Symbol}{"Virt"})
10528 { # override some method in v.2
10529 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010530 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010531 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010532 }
10533 }
10534 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010535 if($Level eq "Binary")
10536 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010537 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010538 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10539 { # check replacements, including pure virtual methods
10540 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10541 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010542 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010543 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10544 if($AddedPos==$RemovedPos)
10545 {
10546 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10547 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10548 last; # other methods will be reported as "added" or "removed"
10549 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010550 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010551 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10552 {
10553 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10554 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010555 next;
10556 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010557 my $ProblemType = "Virtual_Replacement";
10558 my @Affected = ($RemovedVFunc);
10559 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10560 { # pure methods
10561 if(not isUsedClass($ClassId, 1, $Level))
10562 { # not a parameter of some exported method
10563 next;
10564 }
10565 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010566
10567 # affected all methods (both virtual and non-virtual ones)
10568 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10569 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010570 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010571 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010572 foreach my $AffectedInt (@Affected)
10573 {
10574 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10575 { # affected exported methods only
10576 next;
10577 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010578 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10579 next;
10580 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010581 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10582 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010583 "Target"=>get_Signature($AddedVFunc, 2),
10584 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10585 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010586 }
10587 }
10588 }
10589 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010590 if(not checkDump(1, "2.0")
10591 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010592 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010593 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010594 return;
10595 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010596 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010597 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010598 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010599 next if(not $ClassId_Old);
10600 if(not isCreatable($ClassId_Old, 1))
10601 { # skip classes without public constructors (including auto-generated)
10602 # example: class has only a private exported or private inline constructor
10603 next;
10604 }
10605 if($ClassName=~/>/)
10606 { # skip affected template instances
10607 next;
10608 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010609 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010610 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010611 if(not $ClassId_New) {
10612 next;
10613 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010614 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010615 if($Class_New{"Type"}!~/Class|Struct/)
10616 { # became typedef
10617 if($Level eq "Binary") {
10618 next;
10619 }
10620 if($Level eq "Source")
10621 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010622 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010623 if($Class_New{"Type"}!~/Class|Struct/) {
10624 next;
10625 }
10626 $ClassId_New = $Class_New{"Tid"};
10627 }
10628 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010629
10630 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10631 { # incomplete info in the ABI dump
10632 next;
10633 }
10634
10635
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010636 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10637 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 +040010638
10639 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10640 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10641
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010642 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010643 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10644 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010645 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10646 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010647 my $Shift_Old = getShift($ClassId_Old, 1);
10648 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010649 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010650 my ($Added, $Removed) = (0, 0);
10651 my @StableBases_Old = ();
10652 foreach my $BaseId (@Bases_Old)
10653 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010654 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010655 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010656 push(@StableBases_Old, $BaseId);
10657 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010658 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010659 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010660 { # removed base
10661 # excluding namespace::SomeClass to SomeClass renaming
10662 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010663 if($Level eq "Binary")
10664 { # Binary-level
10665 if($Shift_Old ne $Shift_New)
10666 { # affected fields
10667 if(havePubFields(\%Class_Old)) {
10668 $ProblemKind .= "_And_Shift";
10669 }
10670 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10671 $ProblemKind .= "_And_Size";
10672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010673 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010674 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10675 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010676 { # affected v-table
10677 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010678 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010679 }
10680 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010681 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010682 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10683 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010684 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10685 {
10686 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10687 if($ProblemKind=~/VTable/) {
10688 $VTableChanged_M{$SubName}=1;
10689 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010690 }
10691 }
10692 foreach my $Interface (@Affected)
10693 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010694 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10695 next;
10696 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010697 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010698 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010699 "Target"=>$BaseName,
10700 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10701 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10702 "Shift"=>abs($Shift_New-$Shift_Old) );
10703 }
10704 $Removed+=1;
10705 }
10706 }
10707 my @StableBases_New = ();
10708 foreach my $BaseId (@Bases_New)
10709 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010710 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010711 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010712 push(@StableBases_New, $BaseId);
10713 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010714 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010715 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010716 { # added base
10717 # excluding namespace::SomeClass to SomeClass renaming
10718 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010719 if($Level eq "Binary")
10720 { # Binary-level
10721 if($Shift_Old ne $Shift_New)
10722 { # affected fields
10723 if(havePubFields(\%Class_Old)) {
10724 $ProblemKind .= "_And_Shift";
10725 }
10726 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10727 $ProblemKind .= "_And_Size";
10728 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010729 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010730 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10731 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010732 { # affected v-table
10733 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010734 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010735 }
10736 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010737 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010738 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10739 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010740 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10741 {
10742 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10743 if($ProblemKind=~/VTable/) {
10744 $VTableChanged_M{$SubName}=1;
10745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010746 }
10747 }
10748 foreach my $Interface (@Affected)
10749 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010750 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10751 next;
10752 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010753 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010754 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010755 "Target"=>$BaseName,
10756 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10757 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10758 "Shift"=>abs($Shift_New-$Shift_Old) );
10759 }
10760 $Added+=1;
10761 }
10762 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010763 if($Level eq "Binary")
10764 { # Binary-level
10765 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010766 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10767 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010768 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010769 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010770 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010771 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010772 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010773 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10774 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010775 if($NewPos!=$OldPos)
10776 { # changed position of the base class
10777 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010778 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010779 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10780 next;
10781 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010782 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10783 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010784 "Target"=>$BaseName,
10785 "Old_Value"=>$OldPos-1,
10786 "New_Value"=>$NewPos-1 );
10787 }
10788 }
10789 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10790 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10791 { # became non-virtual base
10792 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10793 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010794 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10795 next;
10796 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010797 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10798 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010799 "Target"=>$BaseName );
10800 }
10801 }
10802 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10803 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10804 { # became virtual base
10805 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10806 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010807 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10808 next;
10809 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010810 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10811 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010812 "Target"=>$BaseName );
10813 }
10814 }
10815 }
10816 }
10817 # detect size changes in base classes
10818 if($Shift_Old!=$Shift_New)
10819 { # size of allocable class
10820 foreach my $BaseId (@StableBases_Old)
10821 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010822 my %BaseType = get_Type($BaseId, 1);
10823 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010824 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010825 if($Size_Old ne $Size_New
10826 and $Size_Old and $Size_New)
10827 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010828 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010829 if(isCopyingClass($BaseId, 1)) {
10830 $ProblemType = "Size_Of_Copying_Class";
10831 }
10832 elsif($AllocableClass{1}{$BaseType{"Name"}})
10833 {
10834 if($Size_New>$Size_Old)
10835 { # increased size
10836 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010837 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010838 else
10839 { # decreased size
10840 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10841 if(not havePubFields(\%Class_Old))
10842 { # affected class has no public members
10843 next;
10844 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010845 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010846 }
10847 next if(not $ProblemType);
10848 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10849 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010850 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10851 next;
10852 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010853 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10854 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010855 "Target"=>$BaseType{"Name"},
10856 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10857 "New_Size"=>$Size_New*$BYTE_SIZE );
10858 }
10859 }
10860 }
10861 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010862 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010863 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010864 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010865 { # compare virtual tables size in base classes
10866 my $VShift_Old = getVShift($ClassId_Old, 1);
10867 my $VShift_New = getVShift($ClassId_New, 2);
10868 if($VShift_Old ne $VShift_New)
10869 { # changes in the base class or changes in the list of base classes
10870 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10871 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10872 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010873 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010874 foreach my $BaseId (@AllBases_Old)
10875 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010876 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010877 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010878 { # lost base
10879 next;
10880 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010881 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10882 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010883 if($VSize_Old!=$VSize_New)
10884 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010885 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010886 { # TODO: affected non-virtual methods?
10887 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010888 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10889 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010890 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010891 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010892 { # skip interfaces that have not changed the absolute virtual position
10893 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010894 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010895 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10896 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010897 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010898 $VTableChanged_M{$BaseType{"Name"}} = 1;
10899 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010900 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10901 { # the reason of the layout change: added virtual functions
10902 next if($VirtualReplacement{$VirtFunc});
10903 my $ProblemType = "Added_Virtual_Method";
10904 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10905 $ProblemType = "Added_Pure_Virtual_Method";
10906 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010907 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010908 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010909 "Target"=>get_Signature($VirtFunc, 2) );
10910 }
10911 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10912 { # the reason of the layout change: removed virtual functions
10913 next if($VirtualReplacement{$VirtFunc});
10914 my $ProblemType = "Removed_Virtual_Method";
10915 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10916 $ProblemType = "Removed_Pure_Virtual_Method";
10917 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010918 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010919 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010920 "Target"=>get_Signature($VirtFunc, 1) );
10921 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010922 }
10923 }
10924 }
10925 }
10926 }
10927 }
10928 }
10929}
10930
10931sub isCreatable($$)
10932{
10933 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010934 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010935 or isCopyingClass($ClassId, $LibVersion)) {
10936 return 1;
10937 }
10938 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10939 { # Fix for incomplete data: if this class has
10940 # a base class then it should also has a constructor
10941 return 1;
10942 }
10943 if($ReturnedClass{$LibVersion}{$ClassId})
10944 { # returned by some method of this class
10945 # or any other class
10946 return 1;
10947 }
10948 return 0;
10949}
10950
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010951sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010952{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010953 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010954 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
10955 { # parameter of some exported method
10956 return 1;
10957 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010958 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
10959 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010960 { # method from target class
10961 return 1;
10962 }
10963 return 0;
10964}
10965
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010966sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010967{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010968 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010969 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010970 # - virtual
10971 # - pure-virtual
10972 # - non-virtual
10973 if($CompleteSignature{1}{$Interface}{"Data"})
10974 { # global data is not affected
10975 return;
10976 }
10977 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010978 if(not $Class_Id) {
10979 return;
10980 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010981 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010982 if(cmpVTables_Real($CName, 1)==0)
10983 { # no changes
10984 return;
10985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010986 $CheckedTypes{$Level}{$CName} = 1;
10987 if($Level eq "Binary")
10988 { # Binary-level
10989 if($CompleteSignature{1}{$Interface}{"PureVirt"}
10990 and not isUsedClass($Class_Id, 1, $Level))
10991 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010992 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010993 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010994 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010995 }
10996 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
10997 {
10998 if(defined $VirtualTable{2}{$CName}{$Func}
10999 and defined $CompleteSignature{2}{$Func})
11000 {
11001 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11002 and $CompleteSignature{2}{$Func}{"PureVirt"})
11003 { # became pure virtual
11004 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11005 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011006 "Target"=>get_Signature_M($Func, 1) );
11007 $VTableChanged_M{$CName} = 1;
11008 }
11009 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11010 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11011 { # became non-pure virtual
11012 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11013 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011014 "Target"=>get_Signature_M($Func, 1) );
11015 $VTableChanged_M{$CName} = 1;
11016 }
11017 }
11018 }
11019 if($Level eq "Binary")
11020 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011021 # check virtual table structure
11022 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11023 {
11024 next if($Interface eq $AddedVFunc);
11025 next if($VirtualReplacement{$AddedVFunc});
11026 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11027 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11028 { # pure virtual methods affect all others (virtual and non-virtual)
11029 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011030 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011031 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011032 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011033 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011034 elsif(not defined $VirtualTable{1}{$CName}
11035 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011036 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011037 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011038 { # became polymorphous class, added v-table pointer
11039 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011040 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011041 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011042 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011043 }
11044 else
11045 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011046 my $VSize_Old = getVTable_Size($CName, 1);
11047 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011048 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011049 if(isCopyingClass($Class_Id, 1))
11050 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11051 my $ProblemType = "Added_Virtual_Method";
11052 if(isLeafClass($Class_Id, 1)) {
11053 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11054 }
11055 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11056 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011057 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011058 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011059 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011060 else
11061 {
11062 my $ProblemType = "Added_Virtual_Method";
11063 if(isLeafClass($Class_Id, 1)) {
11064 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11065 }
11066 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11067 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011068 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011069 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011070 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011071 }
11072 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011073 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11074 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011075 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011076 if(defined $VirtualTable{1}{$CName}
11077 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011078 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011079 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11080 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011081
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011082 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011083 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011084 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11085 foreach my $ASymbol (@Affected)
11086 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011087 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11088 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011089 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011090 next;
11091 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011092 }
11093 $CheckedSymbols{$Level}{$ASymbol} = 1;
11094 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11095 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011096 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011097 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011098 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011099 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011100 }
11101 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011102 else {
11103 # safe
11104 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011105 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011106 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11107 {
11108 next if($VirtualReplacement{$RemovedVFunc});
11109 if($RemovedVFunc eq $Interface
11110 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11111 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011112 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011113 next;
11114 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011115 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011116 { # became non-polymorphous class, removed v-table pointer
11117 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11118 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011119 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011120 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011121 }
11122 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11123 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11124 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011125 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011126 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011127 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11128 next;
11129 }
11130 my $VPos_New = -1;
11131 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011132 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011133 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11134 }
11135 else
11136 {
11137 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011138 next;
11139 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011140 }
11141 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11142 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11143 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11144 {
11145 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11146 foreach my $ASymbol (@Affected)
11147 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011148 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11149 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011150 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011151 next;
11152 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011153 }
11154 my $ProblemType = "Removed_Virtual_Method";
11155 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11156 $ProblemType = "Removed_Pure_Virtual_Method";
11157 }
11158 $CheckedSymbols{$Level}{$ASymbol} = 1;
11159 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11160 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011161 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011162 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011163 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011164 }
11165 }
11166 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011167 }
11168 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011169 else
11170 { # Source-level
11171 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011172 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011173 next if($Interface eq $AddedVFunc);
11174 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011175 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011176 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11177 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011178 "Target"=>get_Signature($AddedVFunc, 2) );
11179 }
11180 }
11181 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11182 {
11183 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11184 {
11185 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11186 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011187 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011188 }
11189 }
11190 }
11191}
11192
11193sub find_MemberPair_Pos_byName($$)
11194{
11195 my ($Member_Name, $Pair_Type) = @_;
11196 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11197 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11198 {
11199 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11200 {
11201 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11202 $Name=~s/\A[_]+|[_]+\Z//g;
11203 if($Name eq $Member_Name) {
11204 return $MemberPair_Pos;
11205 }
11206 }
11207 }
11208 return "lost";
11209}
11210
11211sub find_MemberPair_Pos_byVal($$)
11212{
11213 my ($Member_Value, $Pair_Type) = @_;
11214 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11215 {
11216 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11217 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11218 return $MemberPair_Pos;
11219 }
11220 }
11221 return "lost";
11222}
11223
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011224sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011225{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011226 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011227 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011228 if( $_->{"T1"} eq $_[0]
11229 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011230 {
11231 return 1;
11232 }
11233 }
11234 return 0;
11235}
11236
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011237sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011238{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011239 my %IDs = (
11240 "T1" => $_[0],
11241 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011242 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011243 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011244}
11245
11246sub isRenamed($$$$$)
11247{
11248 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11249 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11250 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011251 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011252 if(not defined $Type2->{"Memb"}{$MemPos}) {
11253 return "";
11254 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011255 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011256 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011257
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011258 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11259 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011260 if($MemberPair_Pos_Rev eq "lost")
11261 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011262 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11263 { # base type match
11264 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011265 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011266 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11267 { # exact type match
11268 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011269 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011270 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11271 { # size match
11272 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011273 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011274 if(isReserved($Pair_Name))
11275 { # reserved fields
11276 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011277 }
11278 }
11279 return "";
11280}
11281
11282sub isLastElem($$)
11283{
11284 my ($Pos, $TypeRef) = @_;
11285 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11286 if($Name=~/last|count|max|total/i)
11287 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11288 return 1;
11289 }
11290 elsif($Name=~/END|NLIMITS\Z/)
11291 { # __RLIMIT_NLIMITS
11292 return 1;
11293 }
11294 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11295 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11296 { # NImageFormats, NColorRoles
11297 return 1;
11298 }
11299 return 0;
11300}
11301
11302sub nonComparable($$)
11303{
11304 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011305
11306 my $N1 = $T1->{"Name"};
11307 my $N2 = $T2->{"Name"};
11308
11309 $N1=~s/\A(struct|union|enum) //;
11310 $N2=~s/\A(struct|union|enum) //;
11311
11312 if($N1 ne $N2
11313 and not isAnon($N1)
11314 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011315 { # different names
11316 if($T1->{"Type"} ne "Pointer"
11317 or $T2->{"Type"} ne "Pointer")
11318 { # compare base types
11319 return 1;
11320 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011321 if($N1!~/\Avoid\s*\*/
11322 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011323 {
11324 return 1;
11325 }
11326 }
11327 elsif($T1->{"Type"} ne $T2->{"Type"})
11328 { # different types
11329 if($T1->{"Type"} eq "Class"
11330 and $T2->{"Type"} eq "Struct")
11331 { # "class" to "struct"
11332 return 0;
11333 }
11334 elsif($T2->{"Type"} eq "Class"
11335 and $T1->{"Type"} eq "Struct")
11336 { # "struct" to "class"
11337 return 0;
11338 }
11339 else
11340 { # "class" to "enum"
11341 # "union" to "class"
11342 # ...
11343 return 1;
11344 }
11345 }
11346 return 0;
11347}
11348
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011349sub isOpaque($)
11350{
11351 my $T = $_[0];
11352 if(not defined $T->{"Memb"})
11353 {
11354 return 1;
11355 }
11356 return 0;
11357}
11358
11359sub removeVPtr($)
11360{ # support for old ABI dumps
11361 my $TPtr = $_[0];
11362 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11363 if($#Pos>=1)
11364 {
11365 foreach my $Pos (0 .. $#Pos-1)
11366 {
11367 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11368 }
11369 delete($TPtr->{"Memb"}{$#Pos});
11370 }
11371}
11372
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011373sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011374{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011375 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011376 return {} if(not $Type1_Id or not $Type2_Id);
11377
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011378 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011379 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011380 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011381 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011382
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011383 my %Type1 = get_Type($Type1_Id, 1);
11384 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011385 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011386 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011387 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011388
11389 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011390 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11391 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011392
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011393 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11394
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011395 my %SubProblems = ();
11396
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011397 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11398 {
11399 if($Type1_Pure{"Type"}=~/Struct|Union/
11400 and $Type2_Pure{"Type"}=~/Struct|Union/)
11401 {
11402 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11403 {
11404 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11405 "Target"=>$Type1_Pure{"Name"},
11406 "Type_Name"=>$Type1_Pure{"Name"} );
11407
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011408 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011409 }
11410 }
11411 }
11412
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011413 if(not $Type1_Pure{"Size"}
11414 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011415 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011416 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11417 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11418 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011419 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011420 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011421 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011422 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011423 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011424 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011425 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011426 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11427 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11428 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011429
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011430 if(defined $TargetHeadersPath)
11431 {
11432 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11433 return {};
11434 }
11435 }
11436
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011437 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11438 { # support for old ABI dumps
11439 # _vptr field added in 3.0
11440 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11441 {
11442 if(defined $Type2_Pure{"Memb"}
11443 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11444 {
11445 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11446 delete($Type2_Pure{"Memb"}{0});
11447 }
11448 else {
11449 removeVPtr(\%Type2_Pure);
11450 }
11451 }
11452 }
11453 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11454 {
11455 if(defined $Type1_Pure{"Memb"}
11456 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11457 {
11458 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11459 delete($Type1_Pure{"Memb"}{0});
11460 }
11461 else {
11462 removeVPtr(\%Type1_Pure);
11463 }
11464 }
11465 }
11466 }
11467
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011468 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11469 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011470
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011471 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011472 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11473 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011474 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011475 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11476 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011477 if($Base_1{"Name"} ne $Base_2{"Name"})
11478 {
11479 if(differentDumps("G")
11480 or differentDumps("V"))
11481 { # different GCC versions or different dumps
11482 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11483 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11484 # std::__va_list and __va_list
11485 $Base_1{"Name"}=~s/\A(\w+::)+//;
11486 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011487 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11488 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011489 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011490 }
11491 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11492 and $Base_1{"Name"} ne $Base_2{"Name"})
11493 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011494 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011495 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011496 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011497 {
11498 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11499 "Target"=>$Typedef_1{"Name"},
11500 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011501 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11502 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11503 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011504 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11505 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011506 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011507 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011508 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11509 {
11510 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11511 "Target"=>$Typedef_1{"Name"},
11512 "Type_Name"=>$Typedef_1{"Name"},
11513 "Old_Value"=>$Base_1{"Name"},
11514 "New_Value"=>$Base_2{"Name"} );
11515 }
11516 else
11517 {
11518 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11519 "Target"=>$Typedef_1{"Name"},
11520 "Type_Name"=>$Typedef_1{"Name"},
11521 "Old_Value"=>$Base_1{"Name"},
11522 "New_Value"=>$Base_2{"Name"} );
11523 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011524 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011525 }
11526 }
11527 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11528 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011529 my $TT1 = $Type1_Pure{"Type"};
11530 my $TT2 = $Type2_Pure{"Type"};
11531
11532 if($TT1 ne $TT2
11533 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011534 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011535 my $Short1 = $Type1_Pure{"Name"};
11536 my $Short2 = $Type2_Pure{"Name"};
11537
11538 $Short1=~s/\A\Q$TT1\E //ig;
11539 $Short2=~s/\A\Q$TT2\E //ig;
11540
11541 if($Short1 eq $Short2)
11542 {
11543 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11544 "Target"=>$Type1_Pure{"Name"},
11545 "Type_Name"=>$Type1_Pure{"Name"},
11546 "Old_Value"=>lc($Type1_Pure{"Type"}),
11547 "New_Value"=>lc($Type2_Pure{"Type"}) );
11548 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011549 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011550 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011551 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011552 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011553 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11554 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11555 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11556 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011557 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011558 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011559 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011560 {
11561 my $ProblemKind = "DataType_Size";
11562 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011563 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011564 {
11565 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11566 $ProblemKind = "Size_Of_Copying_Class";
11567 }
11568 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11569 {
11570 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11571 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11572 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011573 else
11574 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011575 # descreased size of allocable class
11576 # it has no special effects
11577 }
11578 }
11579 }
11580 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11581 "Target"=>$Type1_Pure{"Name"},
11582 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011583 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011584 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011585 }
11586 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011587 if(defined $Type1_Pure{"BaseType"}
11588 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011589 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011590 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11591 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011592 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011593 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11594 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011595 }
11596 }
11597 }
11598 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11599 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11600 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11601 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11602 { # detect removed and renamed fields
11603 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11604 next if(not $Member_Name);
11605 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);
11606 if($MemberPair_Pos eq "lost")
11607 {
11608 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11609 {
11610 if(isUnnamed($Member_Name))
11611 { # support for old-version dumps
11612 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011613 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011614 next;
11615 }
11616 }
11617 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11618 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011619 $RenamedField{$Member_Pos} = $RenamedTo;
11620 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011621 }
11622 else
11623 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011624 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011625 }
11626 }
11627 elsif($Type1_Pure{"Type"} eq "Enum")
11628 {
11629 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11630 next if($Member_Value1 eq "");
11631 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11632 if($MemberPair_Pos ne "lost")
11633 { # renamed
11634 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11635 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11636 if($MemberPair_Pos_Rev eq "lost")
11637 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011638 $RenamedField{$Member_Pos} = $RenamedTo;
11639 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011640 }
11641 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011642 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011643 }
11644 }
11645 else
11646 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011647 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011648 }
11649 }
11650 }
11651 else
11652 { # related
11653 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11654 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11655 }
11656 }
11657 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11658 { # detect added fields
11659 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11660 next if(not $Member_Name);
11661 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);
11662 if($MemberPair_Pos eq "lost")
11663 {
11664 if(isUnnamed($Member_Name))
11665 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011666 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011667 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011668 next;
11669 }
11670 }
11671 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11672 {
11673 if(not $RenamedField_Rev{$Member_Pos})
11674 { # added
11675 $AddedField{$Member_Pos}=1;
11676 }
11677 }
11678 }
11679 }
11680 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11681 { # detect moved fields
11682 my (%RelPos, %RelPosName, %AbsPos) = ();
11683 my $Pos = 0;
11684 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11685 { # relative positions in 1st version
11686 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11687 next if(not $Member_Name);
11688 if(not $RemovedField{$Member_Pos})
11689 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011690 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011691 $RelPosName{1}{$Pos} = $Member_Name;
11692 $AbsPos{1}{$Pos++} = $Member_Pos;
11693 }
11694 }
11695 $Pos = 0;
11696 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11697 { # relative positions in 2nd version
11698 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11699 next if(not $Member_Name);
11700 if(not $AddedField{$Member_Pos})
11701 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011702 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011703 $RelPosName{2}{$Pos} = $Member_Name;
11704 $AbsPos{2}{$Pos++} = $Member_Pos;
11705 }
11706 }
11707 foreach my $Member_Name (keys(%{$RelPos{1}}))
11708 {
11709 my $RPos1 = $RelPos{1}{$Member_Name};
11710 my $AbsPos1 = $NameToPosA{$Member_Name};
11711 my $Member_Name2 = $Member_Name;
11712 if(my $RenamedTo = $RenamedField{$AbsPos1})
11713 { # renamed
11714 $Member_Name2 = $RenamedTo;
11715 }
11716 my $RPos2 = $RelPos{2}{$Member_Name2};
11717 if($RPos2 ne "" and $RPos1 ne $RPos2)
11718 { # different relative positions
11719 my $AbsPos2 = $NameToPosB{$Member_Name2};
11720 if($AbsPos1 ne $AbsPos2)
11721 { # different absolute positions
11722 my $ProblemType = "Moved_Field";
11723 if(not isPublic(\%Type1_Pure, $AbsPos1))
11724 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011725 if($Level eq "Source") {
11726 next;
11727 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011728 $ProblemType = "Moved_Private_Field";
11729 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011730 if($Level eq "Binary"
11731 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011732 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011733 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011734 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011735 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011736 if($MemSize1 ne $MemSize2) {
11737 $ProblemType .= "_And_Size";
11738 }
11739 }
11740 if($ProblemType eq "Moved_Private_Field") {
11741 next;
11742 }
11743 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11744 "Target"=>$Member_Name,
11745 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011746 "Old_Value"=>$RPos1,
11747 "New_Value"=>$RPos2 );
11748 }
11749 }
11750 }
11751 }
11752 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011753 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011754 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11755 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011756 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011757 if(my $RenamedTo = $RenamedField{$Member_Pos})
11758 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011759 if(defined $Constants{2}{$Member_Name})
11760 {
11761 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11762 { # define OLD NEW
11763 next; # Safe
11764 }
11765 }
11766
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011767 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11768 {
11769 if(isPublic(\%Type1_Pure, $Member_Pos))
11770 {
11771 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11772 "Target"=>$Member_Name,
11773 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011774 "Old_Value"=>$Member_Name,
11775 "New_Value"=>$RenamedTo );
11776 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011777 elsif(isReserved($Member_Name))
11778 {
11779 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11780 "Target"=>$Member_Name,
11781 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011782 "Old_Value"=>$Member_Name,
11783 "New_Value"=>$RenamedTo );
11784 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011785 }
11786 elsif($Type1_Pure{"Type"} eq "Enum")
11787 {
11788 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11789 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11790 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011791 "Old_Value"=>$Member_Name,
11792 "New_Value"=>$RenamedTo );
11793 }
11794 }
11795 elsif($RemovedField{$Member_Pos})
11796 { # removed
11797 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11798 {
11799 my $ProblemType = "Removed_Field";
11800 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011801 or isUnnamed($Member_Name))
11802 {
11803 if($Level eq "Source") {
11804 next;
11805 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011806 $ProblemType = "Removed_Private_Field";
11807 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011808 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011809 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011810 {
11811 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11812 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011813 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 +040011814 { # changed offset
11815 $ProblemType .= "_And_Layout";
11816 }
11817 }
11818 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11819 { # affected size
11820 $ProblemType .= "_And_Size";
11821 }
11822 }
11823 if($ProblemType eq "Removed_Private_Field") {
11824 next;
11825 }
11826 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11827 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011828 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011829 }
11830 elsif($Type2_Pure{"Type"} eq "Union")
11831 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011832 if($Level eq "Binary"
11833 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011834 {
11835 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11836 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011837 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011838 }
11839 else
11840 {
11841 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11842 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011843 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011844 }
11845 }
11846 elsif($Type1_Pure{"Type"} eq "Enum")
11847 {
11848 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11849 "Target"=>$Member_Name,
11850 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011851 "Old_Value"=>$Member_Name );
11852 }
11853 }
11854 else
11855 { # changed
11856 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11857 if($Type1_Pure{"Type"} eq "Enum")
11858 {
11859 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11860 next if($Member_Value1 eq "");
11861 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11862 next if($Member_Value2 eq "");
11863 if($Member_Value1 ne $Member_Value2)
11864 {
11865 my $ProblemType = "Enum_Member_Value";
11866 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11867 $ProblemType = "Enum_Last_Member_Value";
11868 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011869 if($SkipConstants{1}{$Member_Name}) {
11870 $ProblemType = "Enum_Private_Member_Value";
11871 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011872 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11873 "Target"=>$Member_Name,
11874 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011875 "Old_Value"=>$Member_Value1,
11876 "New_Value"=>$Member_Value2 );
11877 }
11878 }
11879 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11880 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011881 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11882 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11883
11884 if($Access1 ne "private"
11885 and $Access2 eq "private")
11886 {
11887 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11888 "Target"=>$Member_Name,
11889 "Type_Name"=>$Type1_Pure{"Name"});
11890 }
11891 elsif($Access1 ne "protected"
11892 and $Access1 ne "private"
11893 and $Access2 eq "protected")
11894 {
11895 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11896 "Target"=>$Member_Name,
11897 "Type_Name"=>$Type1_Pure{"Name"});
11898 }
11899
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011900 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11901 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011902 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011903 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
11904 $SizeV1 = $BSize1;
11905 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011906 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011907 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
11908 $SizeV2 = $BSize2;
11909 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011910 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
11911 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011912 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011913 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011914 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011915 {
11916 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
11917 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
11918 { # field size change (including anon-structures and unions)
11919 # - same types
11920 # - unnamed types
11921 # - bitfields
11922 my $ProblemType = "Field_Size";
11923 if(not isPublic(\%Type1_Pure, $Member_Pos)
11924 or isUnnamed($Member_Name))
11925 { # should not be accessed by applications, goes to "Low Severity"
11926 # example: "abidata" members in GStreamer types
11927 $ProblemType = "Private_".$ProblemType;
11928 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011929 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 +040011930 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011931 if($Type2_Pure{"Type"} ne "Union"
11932 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011933 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011934 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 +040011935 { # changed offset
11936 $ProblemType .= "_And_Layout";
11937 }
11938 }
11939 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11940 $ProblemType .= "_And_Type_Size";
11941 }
11942 }
11943 if($ProblemType eq "Private_Field_Size")
11944 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011945 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040011946 if($ProblemType eq "Field_Size")
11947 {
11948 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
11949 { # Low severity
11950 $ProblemType = "Struct_Field_Size_Increased";
11951 }
11952 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011953 if($ProblemType)
11954 { # register a problem
11955 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11956 "Target"=>$Member_Name,
11957 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011958 "Old_Size"=>$SizeV1,
11959 "New_Size"=>$SizeV2);
11960 }
11961 }
11962 }
11963 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
11964 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
11965 { # do NOT check bitfield type changes
11966 next;
11967 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011968 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011969 {
11970 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11971 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11972 {
11973 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
11974 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011975 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011976 }
11977 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11978 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11979 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011980 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011981 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011982 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011983 }
11984 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011985 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
11986 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011987 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011988 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
11989 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011990
11991 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011992 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011993 or $ProblemType eq "Field_Type_And_Size"
11994 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011995 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011996 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011997 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011998 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011999 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012000 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012001 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012002 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012003 }
12004 }
12005 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12006 {
12007 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012008 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012009 }
12010 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012011 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012012 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012013 }
12014 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12015 {
12016 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012017 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012018 }
12019 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012020 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012021 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012022 }
12023 }
12024 }
12025
12026 if($Level eq "Source")
12027 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012028 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012029 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012030 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12031 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012032
12033 if($ProblemType eq "Field_Type")
12034 {
12035 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012036 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012037 }
12038 }
12039 }
12040 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012041
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012042 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012043 {
12044 my $ProblemType_Init = $ProblemType;
12045 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012046 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012047 if(not isPublic(\%Type1_Pure, $Member_Pos)
12048 or isUnnamed($Member_Name)) {
12049 $ProblemType = "Private_".$ProblemType;
12050 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012051 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 +040012052 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012053 if($Type2_Pure{"Type"} ne "Union"
12054 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012055 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012056 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 +040012057 { # changed offset
12058 $ProblemType .= "_And_Layout";
12059 }
12060 }
12061 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12062 $ProblemType .= "_And_Type_Size";
12063 }
12064 }
12065 }
12066 else
12067 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012068 # TODO: Private_Field_Type rule?
12069
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012070 if(not isPublic(\%Type1_Pure, $Member_Pos)
12071 or isUnnamed($Member_Name)) {
12072 next;
12073 }
12074 }
12075 if($ProblemType eq "Private_Field_Type_And_Size")
12076 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012077 }
12078 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12079 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012080 "Type_Name"=>$Type1_Pure{"Name"});
12081
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012082 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012083 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012084 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012085 }
12086 }
12087 if(not isPublic(\%Type1_Pure, $Member_Pos))
12088 { # do NOT check internal type changes
12089 next;
12090 }
12091 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012092 { # checking member type changes
12093 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12094
12095 my %DupProblems = ();
12096
12097 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012098 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012099 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012100 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012101 if(not defined $AllAffected)
12102 {
12103 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12104 next;
12105 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012106 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012107
12108 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12109 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12110
12111 if(not defined $AllAffected)
12112 {
12113 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012114 }
12115 }
12116 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012117
12118 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012119 }
12120 }
12121 }
12122 }
12123 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12124 { # checking added members, public and private
12125 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12126 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012127 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012128 if($AddedField{$Member_Pos})
12129 { # added
12130 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12131 {
12132 my $ProblemType = "Added_Field";
12133 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012134 or isUnnamed($Member_Name))
12135 {
12136 if($Level eq "Source") {
12137 next;
12138 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012139 $ProblemType = "Added_Private_Field";
12140 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012141 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012142 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012143 {
12144 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12145 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012146 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 +040012147 { # changed offset
12148 $ProblemType .= "_And_Layout";
12149 }
12150 }
12151 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12152 $ProblemType .= "_And_Size";
12153 }
12154 }
12155 if($ProblemType eq "Added_Private_Field")
12156 { # skip added private fields
12157 next;
12158 }
12159 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12160 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012161 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012162 }
12163 elsif($Type2_Pure{"Type"} eq "Union")
12164 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012165 if($Level eq "Binary"
12166 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012167 {
12168 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12169 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012170 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012171 }
12172 else
12173 {
12174 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12175 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012176 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012177 }
12178 }
12179 elsif($Type2_Pure{"Type"} eq "Enum")
12180 {
12181 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12182 next if($Member_Value eq "");
12183 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12184 "Target"=>$Member_Name,
12185 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012186 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012187 }
12188 }
12189 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012190
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012191 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012192 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012193}
12194
12195sub isUnnamed($) {
12196 return $_[0]=~/\Aunnamed\d+\Z/;
12197}
12198
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012199sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012200{
12201 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012202 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12203 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12204 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12205 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012206 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012207 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012208 }
12209 return $TypeName;
12210}
12211
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012212sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012213{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012214 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012215 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012216 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12217 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012218 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012219 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12220 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012221 return () if(not $Type{"Type"});
12222 if($Type{"Type"} ne $Type_Type)
12223 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012224 return () if(not $Type{"BaseType"});
12225 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012226 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012227 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012228 return %Type;
12229}
12230
12231my %TypeSpecAttributes = (
12232 "Const" => 1,
12233 "Volatile" => 1,
12234 "ConstVolatile" => 1,
12235 "Restrict" => 1,
12236 "Typedef" => 1
12237);
12238
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012239sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012240{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012241 my ($TypeId, $Info) = @_;
12242 if(not $TypeId or not $Info
12243 or not $Info->{$TypeId}) {
12244 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012245 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012246 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12247 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12248 }
12249 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012250 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012251 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012252 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012253 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012254 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012255 return %Type;
12256}
12257
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012258sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012259{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012260 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012261 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012262 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12263 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012264 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012265 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12266 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012267 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12268 my $PLevel = 0;
12269 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12270 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012271 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012272 return $PLevel if(not $Type{"BaseType"});
12273 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12274 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12275 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012276}
12277
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012278sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012279{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012280 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012281 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012282 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12283 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012284 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012285 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12286 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012287 return %Type if(not $Type{"BaseType"});
12288 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012289 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012290 return %Type;
12291}
12292
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012293sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012294{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012295 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012296 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012297 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12298 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012299 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012300 my $Qual = "";
12301 if($Type{"Type"} eq "Pointer") {
12302 $Qual .= "*";
12303 }
12304 elsif($Type{"Type"} eq "Ref") {
12305 $Qual .= "&";
12306 }
12307 elsif($Type{"Type"} eq "ConstVolatile") {
12308 $Qual .= "const volatile";
12309 }
12310 elsif($Type{"Type"} eq "Const"
12311 or $Type{"Type"} eq "Volatile"
12312 or $Type{"Type"} eq "Restrict") {
12313 $Qual .= lc($Type{"Type"});
12314 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012315 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012316 return $BQual.$Qual;
12317}
12318
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012319sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012320{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012321 my ($TypeId, $Info) = @_;
12322 if(not $TypeId or not $Info
12323 or not $Info->{$TypeId}) {
12324 return ();
12325 }
12326 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012327 return %Type if(not $Type{"BaseType"});
12328 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012329 {
12330 if($Info->{$BTid}) {
12331 return %{$Info->{$BTid}};
12332 }
12333 else { # something is going wrong
12334 return ();
12335 }
12336 }
12337 else {
12338 return %Type;
12339 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012340}
12341
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012342sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012343{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012344 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012345 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012346 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12347 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012348}
12349
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012350sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012351{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012352 my $Symbol = $_[0];
12353 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12354}
12355
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012356sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012357 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12358}
12359
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012360sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012361{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012362 my ($SInfo, $LibVersion) = @_;
12363
12364 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012365 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012366 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012367 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012368 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012369 return 1;
12370 }
12371 }
12372 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012373 if(my $ShortName = $SInfo->{"ShortName"})
12374 {
12375 if(index($ShortName,"<")!=-1
12376 and index($ShortName,">")!=-1) {
12377 return 1;
12378 }
12379 }
12380
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012381 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012382}
12383
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012384sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012385{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012386 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012387 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012388 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012389 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012390 { # class specialization
12391 return 1;
12392 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012393 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012394 { # method specialization
12395 return 1;
12396 }
12397 }
12398 return 0;
12399}
12400
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012401sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012402{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012403 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012404
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012405 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012406 { # non-public global data
12407 return 0;
12408 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012409
12410 if(defined $SkipInternal)
12411 {
12412 return 0 if($Symbol=~/($SkipInternal)/);
12413 }
12414
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012415 if($Symbol=~/\A_Z/)
12416 {
12417 if($Symbol=~/[CD][3-4]E/) {
12418 return 0;
12419 }
12420 }
12421
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012422 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012423 { # support for old ABI dumps in --headers-only mode
12424 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12425 {
12426 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12427 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012428 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012429 if(not $PType or $PType eq "Unknown") {
12430 return 0;
12431 }
12432 }
12433 }
12434 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012435 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012436 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012437 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12438
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012439 if($SkipSymbols{$LibVersion}{$Symbol})
12440 { # user defined symbols to ignore
12441 return 0;
12442 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012443
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012444 if($SymbolsListPath and not $SymbolsList{$Symbol})
12445 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012446 if(not $TargetHeadersPath or not $Header
12447 or not is_target_header($Header, 1))
12448 { # -symbols-list | -headers-list
12449 return 0;
12450 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012451 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012452
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012453 if($AppPath and not $SymbolsList_App{$Symbol})
12454 { # user defined symbols (in application)
12455 return 0;
12456 }
12457
12458 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12459
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012460 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12461 if(not $NameSpace and $ClassId)
12462 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012463 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012464 }
12465 if($NameSpace)
12466 { # user defined namespaces to ignore
12467 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12468 return 0;
12469 }
12470 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12471 { # nested namespaces
12472 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12473 return 0;
12474 }
12475 }
12476 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012477 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012478 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012479 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012480 { # --skip-headers or <skip_headers> (not <skip_including>)
12481 if($Skip==1) {
12482 return 0;
12483 }
12484 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012485 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012486 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012487 { # user defined types
12488 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12489
12490 if(not $TypesList{$CName})
12491 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012492 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12493 {
12494 $CName=~s/\A\Q$NS\E\:\://g;
12495 }
12496
12497 if(not $TypesList{$CName})
12498 {
12499 my $Found = 0;
12500
12501 while($CName=~s/\:\:.+?\Z//)
12502 {
12503 if($TypesList{$CName})
12504 {
12505 $Found = 1;
12506 last;
12507 }
12508 }
12509
12510 if(not $Found) {
12511 return 0;
12512 }
12513 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012514 }
12515 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012516
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012517 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12518 { # non-target symbols
12519 return 0;
12520 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012521 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012522 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012523 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12524 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012525 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012526 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12527 { # inline virtual methods
12528 if($Type=~/InlineVirt/) {
12529 return 1;
12530 }
12531 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12532 if(not $Allocable)
12533 { # check bases
12534 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12535 {
12536 if(not isCopyingClass($DCId, $LibVersion))
12537 { # exists a derived class without default c-tor
12538 $Allocable=1;
12539 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012540 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012541 }
12542 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012543 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012544 return 0;
12545 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012546 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012547 else
12548 { # inline non-virtual methods
12549 return 0;
12550 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012551 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012552 }
12553 }
12554 return 1;
12555}
12556
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012557sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012558{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012559 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012560 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12561 {
12562 if(link_symbol($Symbol, 1, "+Deps"))
12563 { # linker can find a new symbol
12564 # in the old-version library
12565 # So, it's not a new symbol
12566 next;
12567 }
12568 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012569 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012570 next;
12571 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012572 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012573 }
12574}
12575
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012576sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012577{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012578 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012579 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12580 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012581 if(link_symbol($Symbol, 2, "+Deps"))
12582 { # linker can find an old symbol
12583 # in the new-version library
12584 next;
12585 }
12586 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012587 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012588 next;
12589 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012590 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012591 }
12592}
12593
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012594sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012595{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012596 my $Level = $_[0];
12597 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012598 { # checking added symbols
12599 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012600 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012601 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012602 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012603 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012604 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012605 { # checking removed symbols
12606 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012607 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012608 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012609 { # skip v-tables for templates, that should not be imported by applications
12610 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012611 if(my $CName = $VTableClass{$Symbol})
12612 {
12613 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12614 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012615 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012616 next;
12617 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012618 }
12619 }
12620 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012621 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012622 }
12623 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12624 { # symbols for pure virtual methods cannot be called by clients
12625 next;
12626 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012627 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012628 }
12629}
12630
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012631sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012632{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012633 my ($LibVersion, $V) = @_;
12634 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12635 return $Cache{"checkDump"}{$LibVersion}{$V};
12636 }
12637 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012638}
12639
12640sub detectAdded_H($)
12641{
12642 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012643 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12644 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012645 if($Level eq "Source")
12646 { # remove symbol version
12647 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12648 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012649
12650 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12651 { # skip artificial constructors
12652 next;
12653 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012654 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012655 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12656 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012657 next;
12658 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012659 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012660 next;
12661 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012662 if(not defined $CompleteSignature{1}{$Symbol}
12663 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12664 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012665 if($UsedDump{2}{"SrcBin"})
12666 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012667 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012668 { # support for old and different (!) ABI dumps
12669 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12670 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012671 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012672 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012673 {
12674 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12675 {
12676 if($Lang eq "C")
12677 { # support for old ABI dumps: missed extern "C" functions
12678 next;
12679 }
12680 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012681 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012682 else
12683 {
12684 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012685 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012686 next;
12687 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012688 }
12689 }
12690 }
12691 }
12692 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012693 }
12694 }
12695}
12696
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012697sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012698{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012699 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012700 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12701 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012702 if($Level eq "Source")
12703 { # remove symbol version
12704 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12705 $Symbol=$SN;
12706 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012707 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12708 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012709 next;
12710 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012711 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012712 next;
12713 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012714 if(not defined $CompleteSignature{2}{$Symbol}
12715 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012716 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012717 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012718 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012719 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012720 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012721 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12722 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012723 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012724 if($CheckHeadersOnly)
12725 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012726 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12727 {
12728 if($Lang eq "C")
12729 { # support for old ABI dumps: missed extern "C" functions
12730 next;
12731 }
12732 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012733 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012734 else
12735 {
12736 if(not link_symbol($Symbol, 1, "-Deps"))
12737 { # skip removed inline symbols
12738 next;
12739 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012740 }
12741 }
12742 }
12743 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012744 if(not checkDump(1, "2.15"))
12745 {
12746 if($Symbol=~/_IT_E\Z/)
12747 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12748 next;
12749 }
12750 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012751 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12752 {
12753 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12754 {
12755 if(defined $Constants{2}{$Short})
12756 {
12757 my $Val = $Constants{2}{$Short}{"Value"};
12758 if(defined $Func_ShortName{2}{$Val})
12759 { # old name defined to new
12760 next;
12761 }
12762 }
12763 }
12764
12765 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012766 $RemovedInt{$Level}{$Symbol} = 1;
12767 if($Level eq "Source")
12768 { # search for a source-compatible equivalent
12769 setAlternative($Symbol, $Level);
12770 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012771 }
12772 }
12773}
12774
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012775sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012776{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012777 my $Level = $_[0];
12778 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012779 { # checking added symbols
12780 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012781 next if($CompleteSignature{2}{$Symbol}{"Private"});
12782 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012783 if($Level eq "Binary")
12784 {
12785 if($CompleteSignature{2}{$Symbol}{"InLine"})
12786 {
12787 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12788 { # skip inline non-virtual functions
12789 next;
12790 }
12791 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012792 }
12793 else
12794 { # Source
12795 if($SourceAlternative_B{$Symbol}) {
12796 next;
12797 }
12798 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012799 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012800 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012801 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012802 { # checking removed symbols
12803 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012804 next if($CompleteSignature{1}{$Symbol}{"Private"});
12805 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012806 if($Level eq "Binary")
12807 {
12808 if($CompleteSignature{1}{$Symbol}{"InLine"})
12809 {
12810 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12811 { # skip inline non-virtual functions
12812 next;
12813 }
12814 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012815 }
12816 else
12817 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012818 if(my $Alt = $SourceAlternative{$Symbol})
12819 {
12820 if(defined $CompleteSignature{1}{$Alt}
12821 and $CompleteSignature{1}{$Symbol}{"Const"})
12822 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012823 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012824 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012825 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012826 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012827 }
12828 else
12829 { # do NOT show removed symbol
12830 next;
12831 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012832 }
12833 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012834 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012835 }
12836}
12837
12838sub addParamNames($)
12839{
12840 my $LibraryVersion = $_[0];
12841 return if(not keys(%AddIntParams));
12842 my $SecondVersion = $LibraryVersion==1?2:1;
12843 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
12844 {
12845 next if(not keys(%{$AddIntParams{$Interface}}));
12846 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012847 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012848 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
12849 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012850 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012851 if(defined $CompleteSignature{$SecondVersion}{$Interface}
12852 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
12853 {
12854 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
12855 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12856 }
12857 }
12858 else {
12859 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12860 }
12861 }
12862 }
12863 }
12864}
12865
12866sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012867{ # detect changed typedefs to show
12868 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012869 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
12870 {
12871 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012872 my $BName1 = $Typedef_BaseName{1}{$Typedef};
12873 if(not $BName1 or isAnon($BName1)) {
12874 next;
12875 }
12876 my $BName2 = $Typedef_BaseName{2}{$Typedef};
12877 if(not $BName2 or isAnon($BName2)) {
12878 next;
12879 }
12880 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012881 $ChangedTypedef{$Typedef} = 1;
12882 }
12883 }
12884}
12885
12886sub get_symbol_suffix($$)
12887{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012888 my ($Symbol, $Full) = @_;
12889 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040012890 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012891 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012892 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012893 if(not $Full) {
12894 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
12895 }
12896 return $Suffix;
12897}
12898
12899sub get_symbol_prefix($$)
12900{
12901 my ($Symbol, $LibVersion) = @_;
12902 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
12903 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12904 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012905 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012906 }
12907 return $ShortName;
12908}
12909
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012910sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012911{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012912 my $Symbol = $_[0];
12913 my $PSymbol = $Symbol;
12914 if(not defined $CompleteSignature{2}{$PSymbol}
12915 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
12916 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
12917 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012918 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012919 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012920 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012921 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012922 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
12923 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012924 {
12925 if(defined $CompleteSignature{2}{$PSymbol}
12926 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12927 {
12928 $SourceAlternative{$Symbol} = $PSymbol;
12929 $SourceAlternative_B{$PSymbol} = $Symbol;
12930 if(not defined $CompleteSignature{1}{$PSymbol}
12931 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12932 $SourceReplacement{$Symbol} = $PSymbol;
12933 }
12934 }
12935 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012936 }
12937 else
12938 {
12939 foreach my $Sp ("KV", "VK", "K", "V")
12940 {
12941 if($PSymbol=~s/\A_ZN$Sp/_ZN/
12942 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
12943 {
12944 if(defined $CompleteSignature{2}{$PSymbol}
12945 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12946 {
12947 $SourceAlternative{$Symbol} = $PSymbol;
12948 $SourceAlternative_B{$PSymbol} = $Symbol;
12949 if(not defined $CompleteSignature{1}{$PSymbol}
12950 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12951 $SourceReplacement{$Symbol} = $PSymbol;
12952 }
12953 }
12954 }
12955 $PSymbol = $Symbol;
12956 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012957 }
12958 }
12959 }
12960 return "";
12961}
12962
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012963sub getSymKind($$)
12964{
12965 my ($Symbol, $LibVersion) = @_;
12966 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
12967 {
12968 return "Global_Data";
12969 }
12970 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12971 {
12972 return "Method";
12973 }
12974 return "Function";
12975}
12976
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040012977sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012978{
12979 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012980 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012981
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012982 mergeBases($Level);
12983
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012984 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012985 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012986 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012987 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012988 next;
12989 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012990 if(defined $CompleteSignature{1}{$Symbol}
12991 and $CompleteSignature{1}{$Symbol}{"Header"})
12992 { # double-check added symbol
12993 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012994 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012995 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012996 next;
12997 }
12998 if($Symbol=~/\A(_Z|\?)/)
12999 { # C++
13000 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13001 }
13002 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13003 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013004 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13005 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013006 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013007 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013008 {
13009 if($TName_Tid{1}{$AffectedClass_Name})
13010 { # class should exist in previous version
13011 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13012 { # old v-table is NOT copied by old applications
13013 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13014 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013015 "Target"=>get_Signature($Symbol, 2),
13016 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013017 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013018 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013019 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013020 }
13021 }
13022 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013023 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13024 { # check all removed exported symbols
13025 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013026 next;
13027 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013028 if(defined $CompleteSignature{2}{$Symbol}
13029 and $CompleteSignature{2}{$Symbol}{"Header"})
13030 { # double-check removed symbol
13031 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013032 }
13033 if($CompleteSignature{1}{$Symbol}{"Private"})
13034 { # skip private methods
13035 next;
13036 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013037 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013038 next;
13039 }
13040 $CheckedSymbols{$Level}{$Symbol} = 1;
13041 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13042 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013043 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13044 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013045 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013046 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13047 {
13048 if($TName_Tid{2}{$AffectedClass_Name})
13049 { # class should exist in newer version
13050 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13051 { # old v-table is NOT copied by old applications
13052 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13053 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013054 "Target"=>get_Signature($OverriddenMethod, 1),
13055 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013056 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013057 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013058 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013059 }
13060 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013061 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013062 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013063 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013064 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013065 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013066 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013067 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013068 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013069 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013070 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013071 {
13072 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13073 "Target"=>$tr_name{$Symbol},
13074 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013075 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013076 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013077 else
13078 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013079 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013080 "Target"=>$tr_name{$Symbol},
13081 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013082 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013083 }
13084 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013085 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013086 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013087 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013088 {
13089 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13090 "Target"=>$tr_name{$Symbol},
13091 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013092 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013093 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013094 else
13095 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013096 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013097 "Target"=>$tr_name{$Symbol},
13098 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013099 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013100 }
13101 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013102 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13103 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13104 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13105 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13106 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013107 {
13108 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013109 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013110 $ProblemType = "Global_Data_Symbol_Changed_Type";
13111 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013112 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13113 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013114 "Old_Type"=>$RTName1,
13115 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013116 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013117 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013118 }
13119 }
13120 }
13121 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013122 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013123 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013124 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013125 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013126 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013127 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013128 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013129 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13130 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013131 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013132 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013133 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013134 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013135 }
13136 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013137 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13138 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013139 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013140 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013141 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013142 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013143 }
13144 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013145 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013146 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013147 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013148 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013149 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013150 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013151 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013152 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013153 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013154 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013155 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013156 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013157 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013158 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013159 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013160 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013161 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013162 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013163 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013164 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013165 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013166 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013167 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013168 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013169 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013170 { # "volatile" to non-"volatile"
13171
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013172 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013173 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013174 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013175 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013176 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013177 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013178 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013179 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013180 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013181 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013182 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013183 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013184 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013185 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013186 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013187 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013188 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013189 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13190 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013191 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013192 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013193 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013194 }
13195 }
13196 }
13197 }
13198 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013199 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13200 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013201 $CurrentSymbol = $Symbol;
13202
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013203 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13204 if($Level eq "Source")
13205 { # remove symbol version
13206 $Symbol=$SN;
13207 }
13208 else
13209 { # Binary
13210 if(not $SV)
13211 { # symbol without version
13212 if(my $VSym = $SymVer{1}{$Symbol})
13213 { # the symbol is linked with versioned symbol
13214 if($CompleteSignature{2}{$VSym}{"MnglName"})
13215 { # show report for symbol@ver only
13216 next;
13217 }
13218 elsif(not link_symbol($VSym, 2, "-Deps"))
13219 { # changed version: sym@v1 to sym@v2
13220 # do NOT show report for symbol
13221 next;
13222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013223 }
13224 }
13225 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013226 my $PSymbol = $Symbol;
13227 if($Level eq "Source"
13228 and my $S = $SourceReplacement{$Symbol})
13229 { # take a source-compatible replacement function
13230 $PSymbol = $S;
13231 }
13232 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013233 { # private symbols
13234 next;
13235 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013236 if(not defined $CompleteSignature{1}{$Symbol}
13237 or not defined $CompleteSignature{2}{$PSymbol})
13238 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013239 next;
13240 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013241 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13242 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13243 { # no mangled name
13244 next;
13245 }
13246 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13247 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013248 { # without a header
13249 next;
13250 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013251
13252 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13253 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13254 { # became pure
13255 next;
13256 }
13257 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13258 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13259 { # became non-pure
13260 next;
13261 }
13262
13263 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13264 { # exported, target, inline virtual and pure virtual
13265 next;
13266 }
13267 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13268 { # exported, target, inline virtual and pure virtual
13269 next;
13270 }
13271
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013272 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013273 {
13274 if($CompleteSignature{1}{$Symbol}{"Data"}
13275 and $CompleteSignature{2}{$PSymbol}{"Data"})
13276 {
13277 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13278 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13279 if(defined $Value1)
13280 {
13281 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13282 if(defined $Value2)
13283 {
13284 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13285 if($Value1 ne $Value2)
13286 {
13287 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13288 "Old_Value"=>$Value1,
13289 "New_Value"=>$Value2,
13290 "Target"=>get_Signature($Symbol, 1) );
13291 }
13292 }
13293 }
13294 }
13295 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013296
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013297 if($CompleteSignature{2}{$PSymbol}{"Private"})
13298 {
13299 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13300 "Target"=>get_Signature_M($PSymbol, 2) );
13301 }
13302 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13303 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13304 {
13305 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13306 "Target"=>get_Signature_M($PSymbol, 2) );
13307 }
13308 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13309 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13310 {
13311 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13312 "Target"=>get_Signature_M($PSymbol, 2) );
13313 }
13314
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013315 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013316 mergeVirtualTables($Symbol, $Level);
13317
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013318 if($COMPILE_ERRORS)
13319 { # if some errors occurred at the compiling stage
13320 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013321 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013322 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013323 { # missed information about parameters in newer version
13324 next;
13325 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013326 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013327 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013328 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013329 next;
13330 }
13331 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013332 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013333 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013334 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013335 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13336 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013337 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13338 "Target"=>get_Signature($Symbol, 1)
13339 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013340 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013341 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013342 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13343 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013344 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013345 "Target"=>get_Signature($Symbol, 1)
13346 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013347 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013348 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13349 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013350 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013351 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013352 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013353 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13354 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13355 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013356 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013357 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013358 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13359 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013360 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013361 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013362 my $ProblemType = "Virtual_Method_Position";
13363 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13364 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013365 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013366 if(isUsedClass($Class_Id, 1, $Level))
13367 {
13368 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013369 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013370 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013371 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13372 next;
13373 }
13374 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013375 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013376 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13377 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013378 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013379 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013380 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013381 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013382 }
13383 }
13384 }
13385 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013386 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13387 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013388 { # do NOT check type changes in pure virtuals
13389 next;
13390 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013391 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013392 if($Symbol=~/\A(_Z|\?)/
13393 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013394 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013395 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013396 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013397 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013398 }
13399 }
13400 else
13401 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013402 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013403 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013404 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013405 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13406 last if($PType2_Name eq "...");
13407 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13408 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013409 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013410 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013411 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013412 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13413 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013414 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13415 $ParamPos_Prev = "lost";
13416 }
13417 }
13418 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013419 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013420 }
13421 if($ParamPos_Prev eq "lost")
13422 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013423 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013424 {
13425 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013426 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013427 $ProblemType = "Added_Unnamed_Parameter";
13428 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013429 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013430 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013431 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013432 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013433 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013434 }
13435 else
13436 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013437 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013438 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013439 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013440 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13441 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013442 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013443 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013444 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013445 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013446 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013447 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013448 "Param_Type"=>$PType2_Name,
13449 "Old_Value"=>$PName_Old,
13450 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013451 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013452 }
13453 }
13454 else
13455 {
13456 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013457 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013458 $ProblemType = "Added_Middle_Unnamed_Parameter";
13459 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013460 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013461 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013462 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013463 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013464 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013465 }
13466 }
13467 }
13468 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013469 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013470 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013471 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013472 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013473 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013474 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013475 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013476 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013477 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013478 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13479 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013480 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013481 }
13482 }
13483 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013484 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013485 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013486 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013487 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13488 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013489 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13490 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013491 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013492 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013493 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013494 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13495 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013496 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13497 $ParamPos_New = "lost";
13498 }
13499 }
13500 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013501 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013502 }
13503 if($ParamPos_New eq "lost")
13504 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013505 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013506 {
13507 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013508 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013509 $ProblemType = "Removed_Unnamed_Parameter";
13510 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013511 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013512 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013513 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013514 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013515 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013516 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013517 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013518 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013519 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013520 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013521 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013522 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013523 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013524 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013525 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013526 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013527 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013528 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013529 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013530 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013531 "Old_Value"=>$PName,
13532 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013533 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013534 }
13535 }
13536 else
13537 {
13538 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013539 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013540 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13541 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013542 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013543 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013544 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013545 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013546 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013547 }
13548 }
13549 }
13550 }
13551 }
13552 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013553 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13554 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013555 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013556
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013557 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013558 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013559 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13560 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013561 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013562
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013563 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013564 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013565 if($SubProblemType eq "Return_Type_And_Size") {
13566 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13567 }
13568 elsif($SubProblemType eq "Return_Type_Format") {
13569 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13570 }
13571 else {
13572 $ProblemTypes{"Global_Data_Type"} = 1;
13573 }
13574
13575 # quals
13576 if($SubProblemType eq "Return_Type"
13577 or $SubProblemType eq "Return_Type_And_Size"
13578 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013579 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013580 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13581 { # const to non-const
13582 if($RR==2) {
13583 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13584 }
13585 else {
13586 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13587 }
13588 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013589 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013590 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13591 { # non-const to const
13592 if($RA==2) {
13593 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13594 }
13595 else {
13596 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13597 }
13598 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013599 }
13600 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013601 }
13602 else
13603 {
13604 # quals
13605 if($SubProblemType eq "Return_Type"
13606 or $SubProblemType eq "Return_Type_And_Size"
13607 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013608 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013609 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013610 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013611 if(addedQual($Old_Value, $New_Value, "volatile"))
13612 {
13613 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13614 if($Level ne "Source"
13615 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13616 $ProblemTypes{"Return_Type"} = 1;
13617 }
13618 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013619 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013620 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13621 {
13622 if($RA==2) {
13623 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13624 }
13625 else {
13626 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13627 }
13628 if($Level ne "Source"
13629 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13630 $ProblemTypes{"Return_Type"} = 1;
13631 }
13632 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013633 }
13634 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013635 if($Level eq "Binary"
13636 and not $CompleteSignature{1}{$Symbol}{"Data"})
13637 {
13638 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13639 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13640 { # if one of the architectures is unknown
13641 # then set other arhitecture to unknown too
13642 ($Arch1, $Arch2) = ("unknown", "unknown");
13643 }
13644 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013645 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013646 {
13647 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13648 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13649 }
13650 else
13651 {
13652 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13653 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13654 }
13655
13656 if($SubProblemType eq "Return_Type_Became_Void")
13657 {
13658 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13659 { # parameters stack has been affected
13660 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013661 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013662 }
13663 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013664 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013665 }
13666 }
13667 }
13668 elsif($SubProblemType eq "Return_Type_From_Void")
13669 {
13670 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13671 { # parameters stack has been affected
13672 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013673 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013674 }
13675 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013676 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013677 }
13678 }
13679 }
13680 elsif($SubProblemType eq "Return_Type"
13681 or $SubProblemType eq "Return_Type_And_Size"
13682 or $SubProblemType eq "Return_Type_Format")
13683 {
13684 if($Conv1{"Method"} ne $Conv2{"Method"})
13685 {
13686 if($Conv1{"Method"} eq "stack")
13687 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013688 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013689 }
13690 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013691 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013692 }
13693 }
13694 else
13695 {
13696 if($Conv1{"Method"} eq "reg")
13697 {
13698 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13699 {
13700 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013701 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013702 }
13703 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013704 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013705 }
13706 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013707 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013708 }
13709 }
13710 }
13711 }
13712 }
13713 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013714
13715 if(not keys(%ProblemTypes))
13716 { # default
13717 $ProblemTypes{$SubProblemType} = 1;
13718 }
13719
13720 foreach my $ProblemType (keys(%ProblemTypes))
13721 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013722 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013723 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013724 }
13725 if($ReturnType1_Id and $ReturnType2_Id)
13726 {
13727 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013728 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13729
13730 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013731
13732 if($CompleteSignature{1}{$Symbol}{"Data"})
13733 {
13734 if($Level eq "Binary")
13735 {
13736 if(get_PLevel($ReturnType1_Id, 1)==0)
13737 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013738 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013739 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013740
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013741 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13742 {
13743 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013744 {
13745 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13746 {
13747 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13748 last;
13749 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013750 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013751 }
13752 }
13753 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013754 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013755 {
13756 if(defined $GlobalDataObject{1}{$Symbol}
13757 and defined $GlobalDataObject{2}{$Symbol})
13758 {
13759 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13760 my $New_Size = $GlobalDataObject{2}{$Symbol};
13761 if($Old_Size!=$New_Size)
13762 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013763 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013764 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013765 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013766 }
13767 }
13768 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013769 }
13770 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013771
13772 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013773 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013774 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013775 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013776 my $NewLocation = "retval";
13777 if($SubLocation and $SubLocation ne "retval") {
13778 $NewLocation = "retval->".$SubLocation;
13779 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013780 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13781 }
13782 }
13783
13784 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13785 {
13786 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13787 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013788 my $NewLocation = "retval";
13789 if($SubLocation and $SubLocation ne "retval") {
13790 $NewLocation = "retval->".$SubLocation;
13791 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013792 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013793 }
13794 }
13795 }
13796
13797 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013798 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13799 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13800 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013801 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013802 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013803 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13804 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013805 if($ThisPtr1_Id and $ThisPtr2_Id)
13806 {
13807 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013808 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13809 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013810 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013811 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013812 {
13813 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013814 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013815 }
13816 }
13817 }
13818 }
13819 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013820 if($Level eq "Binary") {
13821 mergeVTables($Level);
13822 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013823 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13824 $CheckedSymbols{$Level}{$Symbol} = 1;
13825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013826}
13827
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013828sub rmQuals($$)
13829{
13830 my ($Value, $Qual) = @_;
13831 if(not $Qual) {
13832 return $Value;
13833 }
13834 if($Qual eq "all")
13835 { # all quals
13836 $Qual = "const|volatile|restrict";
13837 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013838 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013839 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013840 }
13841 return $Value;
13842}
13843
13844sub cmpBTypes($$$$)
13845{
13846 my ($T1, $T2, $V1, $V2) = @_;
13847 $T1 = uncover_typedefs($T1, $V1);
13848 $T2 = uncover_typedefs($T2, $V2);
13849 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
13850}
13851
13852sub addedQual($$$)
13853{
13854 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013855 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013856}
13857
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013858sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013859{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013860 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013861 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013862}
13863
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013864sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013865{
13866 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
13867 $Old_Value = uncover_typedefs($Old_Value, $V1);
13868 $New_Value = uncover_typedefs($New_Value, $V2);
13869 if($Old_Value eq $New_Value)
13870 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013871 return 0;
13872 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013873 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013874 { # without a qual
13875 return 0;
13876 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013877 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013878 { # became non-qual
13879 return 1;
13880 }
13881 else
13882 {
13883 my @BQ1 = getQualModel($Old_Value, $Qual);
13884 my @BQ2 = getQualModel($New_Value, $Qual);
13885 foreach (0 .. $#BQ1)
13886 { # removed qual
13887 if($BQ1[$_]==1
13888 and $BQ2[$_]!=1)
13889 {
13890 return 2;
13891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013892 }
13893 }
13894 return 0;
13895}
13896
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013897sub getQualModel($$)
13898{
13899 my ($Value, $Qual) = @_;
13900 if(not $Qual) {
13901 return $Value;
13902 }
13903
13904 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013905 while($Value=~/(\w+)/ and $1 ne $Qual) {
13906 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013907 }
13908 $Value=~s/[^\*\&\w]+//g;
13909
13910 # modeling
13911 # int*const*const == 011
13912 # int**const == 001
13913 my @Model = ();
13914 my @Elems = split(/[\*\&]/, $Value);
13915 if(not @Elems) {
13916 return (0);
13917 }
13918 foreach (@Elems)
13919 {
13920 if($_ eq $Qual) {
13921 push(@Model, 1);
13922 }
13923 else {
13924 push(@Model, 0);
13925 }
13926 }
13927
13928 return @Model;
13929}
13930
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013931my %StringTypes = map {$_=>1} (
13932 "char*",
13933 "char const*"
13934);
13935
13936my %CharTypes = map {$_=>1} (
13937 "char",
13938 "char const"
13939);
13940
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013941sub showVal($$$)
13942{
13943 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013944 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040013945 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013946 if(substr($Value, 0, 2) eq "_Z")
13947 {
13948 if(my $Unmangled = $tr_name{$Value}) {
13949 return $Unmangled;
13950 }
13951 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013952 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013953 { # strings
13954 return "\"$Value\"";
13955 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013956 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013957 { # characters
13958 return "\'$Value\'";
13959 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013960 if($Value eq "")
13961 { # other
13962 return "\'\'";
13963 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013964 return $Value;
13965}
13966
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013967sub getRegs($$$)
13968{
13969 my ($LibVersion, $Symbol, $Pos) = @_;
13970
13971 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
13972 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013973 my %Regs = ();
13974 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
13975 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013976 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013977 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
13978 }
13979 }
13980
13981 return join(", ", sort keys(%Regs));
13982 }
13983
13984 return undef;
13985}
13986
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013987sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013988{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013989 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013990 if(not $Symbol) {
13991 return;
13992 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013993 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
13994 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
13995 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
13996 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013997 if(not $PType1_Id
13998 or not $PType2_Id) {
13999 return;
14000 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014001
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014002 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014003 { # do not merge "this"
14004 if($PName1 eq "this" or $PName2 eq "this") {
14005 return;
14006 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014007 }
14008
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014009 my %Type1 = get_Type($PType1_Id, 1);
14010 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014011
14012 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14013
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014014 my %BaseType1 = get_BaseType($PType1_Id, 1);
14015 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014016
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014017 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014018
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014019 if($Level eq "Binary")
14020 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014021 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014022 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14023 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14024 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14025 {
14026 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014027 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014028 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014029 }
14030 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14031 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14032 {
14033 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014034 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014035 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014036 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014037 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014038
14039 if(defined $UsedDump{1}{"DWARF"}
14040 and defined $UsedDump{2}{"DWARF"})
14041 {
14042 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14043 {
14044 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14045 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14046 if($Old_Regs and $New_Regs)
14047 {
14048 if($Old_Regs ne $New_Regs)
14049 {
14050 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14051 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014052 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014053 "Old_Value"=>$Old_Regs,
14054 "New_Value"=>$New_Regs );
14055 }
14056 }
14057 elsif($Old_Regs and not $New_Regs)
14058 {
14059 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14060 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014061 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014062 "Old_Value"=>$Old_Regs );
14063 }
14064 elsif(not $Old_Regs and $New_Regs)
14065 {
14066 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14067 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014068 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014069 "New_Value"=>$New_Regs );
14070 }
14071 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14072 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14073 {
14074 if($Old_Offset ne $New_Offset)
14075 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014076 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14077 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14078
14079 $Old_Offset = $Old_Offset - $Start1;
14080 $New_Offset = $New_Offset - $Start2;
14081
14082 if($Old_Offset ne $New_Offset)
14083 {
14084 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14085 "Target"=>$PName1,
14086 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14087 "Old_Value"=>$Old_Offset,
14088 "New_Value"=>$New_Offset );
14089 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014090 }
14091 }
14092 }
14093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014094 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014095 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14096 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014097 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014098 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014099 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14100 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014101 if(not checkDump(1, "2.13")
14102 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014103 { # support for old ABI dumps
14104 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014105 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014106 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014107 and $Value_Old eq "false" and $Value_New eq "0")
14108 { # int class::method ( bool p = 0 );
14109 # old ABI dumps: "false"
14110 # new ABI dumps: "0"
14111 $Value_Old = "0";
14112 }
14113 }
14114 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014115 if(not checkDump(1, "2.18")
14116 and checkDump(2, "2.18"))
14117 { # support for old ABI dumps
14118 if(not defined $Value_Old
14119 and substr($Value_New, 0, 2) eq "_Z") {
14120 $Value_Old = $Value_New;
14121 }
14122 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014123 if(defined $Value_Old)
14124 {
14125 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14126 if(defined $Value_New)
14127 {
14128 $Value_New = showVal($Value_New, $PType2_Id, 2);
14129 if($Value_Old ne $Value_New)
14130 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014131 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014132 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014133 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014134 "Old_Value"=>$Value_Old,
14135 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014136 }
14137 }
14138 else
14139 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014140 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014141 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014142 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014143 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014144 }
14145 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014146 elsif(defined $Value_New)
14147 {
14148 $Value_New = showVal($Value_New, $PType2_Id, 2);
14149 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14150 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014151 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014152 "New_Value"=>$Value_New );
14153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014154 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014155
14156 if($ChkRnmd)
14157 {
14158 if($PName1 and $PName2 and $PName1 ne $PName2
14159 and $PType1_Id!=-1 and $PType2_Id!=-1
14160 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14161 { # except unnamed "..." value list (Id=-1)
14162 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14163 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014164 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014165 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14166 "Old_Value"=>$PName1,
14167 "New_Value"=>$PName2,
14168 "New_Signature"=>get_Signature($Symbol, 2) );
14169 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014170 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014171
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014172 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014173 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014174
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014175 foreach my $SubProblemType (keys(%SubProblems))
14176 { # add new problems, remove false alarms
14177 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14178 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014179
14180 # quals
14181 if($SubProblemType eq "Parameter_Type"
14182 or $SubProblemType eq "Parameter_Type_And_Size"
14183 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014184 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014185 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014186 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014187 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014188 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014189 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014190 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14191 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14192 }
14193 }
14194 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14195 {
14196 if(removedQual($Old_Value, $New_Value, "volatile")) {
14197 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014198 }
14199 }
14200 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14201 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14202 { # int to "int const"
14203 delete($SubProblems{$SubProblemType});
14204 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014205 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014206 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14207 { # "int const" to int
14208 delete($SubProblems{$SubProblemType});
14209 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014210 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14211 { # "const" to non-"const"
14212 if($RR==2) {
14213 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14214 }
14215 else {
14216 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14217 }
14218 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014219 }
14220 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014221
14222 if($Level eq "Source")
14223 {
14224 foreach my $SubProblemType (keys(%SubProblems))
14225 {
14226 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14227 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14228
14229 if($SubProblemType eq "Parameter_Type")
14230 {
14231 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14232 delete($SubProblems{$SubProblemType});
14233 }
14234 }
14235 }
14236 }
14237
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014238 foreach my $SubProblemType (keys(%SubProblems))
14239 { # modify/register problems
14240 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14241 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014242 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14243 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014244
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014245 my $NewProblemType = $SubProblemType;
14246 if($Old_Value eq "..." and $New_Value ne "...")
14247 { # change from "..." to "int"
14248 if($ParamPos1==0)
14249 { # ISO C requires a named argument before "..."
14250 next;
14251 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014252 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014253 }
14254 elsif($New_Value eq "..." and $Old_Value ne "...")
14255 { # change from "int" to "..."
14256 if($ParamPos2==0)
14257 { # ISO C requires a named argument before "..."
14258 next;
14259 }
14260 $NewProblemType = "Parameter_Became_VaList";
14261 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014262 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014263 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014264 {
14265 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014266 if($Arch1 eq "unknown"
14267 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014268 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014269 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014270 ($Arch1, $Arch2) = ("unknown", "unknown");
14271 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014272 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014273 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014274 { # real
14275 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14276 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14277 }
14278 else
14279 { # model
14280 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14281 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14282 }
14283 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014284 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014285 if($Conv1{"Method"} eq "stack")
14286 {
14287 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14288 $NewProblemType = "Parameter_Type_And_Stack";
14289 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014290 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014291 elsif($Conv1{"Method"} eq "reg")
14292 {
14293 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14294 $NewProblemType = "Parameter_Type_And_Register";
14295 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014296 }
14297 }
14298 else
14299 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014300 if($Conv1{"Method"} eq "stack") {
14301 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014302 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014303 elsif($Conv1{"Method"} eq "register") {
14304 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014305 }
14306 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014307 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14308 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014309 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014310 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014311 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014312 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014313 "New_Signature"=>get_Signature($Symbol, 2) );
14314 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014315 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014316
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014317 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014318
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014319 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014320 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14321 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014322 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014323 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014324 {
14325 my $NewProblemType = $SubProblemType;
14326 if($SubProblemType eq "DataType_Size")
14327 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014328 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014329 { # stack has been affected
14330 $NewProblemType = "DataType_Size_And_Stack";
14331 }
14332 }
14333 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014334 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014335 }
14336 }
14337}
14338
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014339sub find_ParamPair_Pos_byName($$$)
14340{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014341 my ($Name, $Symbol, $LibVersion) = @_;
14342 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014343 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014344 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14345 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014346 {
14347 return $ParamPos;
14348 }
14349 }
14350 return "lost";
14351}
14352
14353sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14354{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014355 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014356 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014357 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014358 {
14359 next if($Order eq "backward" and $ParamPos>$MediumPos);
14360 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014361 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14362 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014363 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014364 push(@Positions, $ParamPos);
14365 }
14366 }
14367 return @Positions;
14368}
14369
14370sub getTypeIdByName($$)
14371{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014372 my ($TypeName, $LibVersion) = @_;
14373 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014374}
14375
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014376sub diffTypes($$$)
14377{
14378 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14379 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14380 }
14381 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14382 { # skip recursive declarations
14383 return 0;
14384 }
14385
14386 pushType($_[0], $_[1], \@RecurTypes_Diff);
14387 my $Diff = diffTypes_I(@_);
14388 pop(@RecurTypes_Diff);
14389
14390 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14391}
14392
14393sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014394{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014395 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014396
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014397 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14398 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014399
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014400 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14401 { # equal types
14402 return 0;
14403 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014404 if($Type1_Pure{"Name"} eq "void")
14405 { # from void* to something
14406 return 0;
14407 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014408 if($Type1_Pure{"Name"}=~/\*/
14409 or $Type2_Pure{"Name"}=~/\*/)
14410 { # compared in detectTypeChange()
14411 return 0;
14412 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014413
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014414 my %FloatType = map {$_=>1} (
14415 "float",
14416 "double",
14417 "long double"
14418 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014419
14420 my $T1 = $Type1_Pure{"Type"};
14421 my $T2 = $Type2_Pure{"Type"};
14422
14423 if($T1 eq "Struct"
14424 and $T2 eq "Class")
14425 { # compare as data structures
14426 $T2 = "Struct";
14427 }
14428
14429 if($T1 eq "Class"
14430 and $T2 eq "Struct")
14431 { # compare as data structures
14432 $T1 = "Struct";
14433 }
14434
14435 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014436 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014437 if($T1 eq "Intrinsic"
14438 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014439 { # "int" to "enum"
14440 return 0;
14441 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014442 elsif($T2 eq "Intrinsic"
14443 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014444 { # "enum" to "int"
14445 return 0;
14446 }
14447 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014448 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014449 # ...
14450 return 1;
14451 }
14452 }
14453 else
14454 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014455 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014456 {
14457 if($FloatType{$Type1_Pure{"Name"}}
14458 or $FloatType{$Type2_Pure{"Name"}})
14459 { # "float" to "double"
14460 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014461 if($Level eq "Source")
14462 { # Safe
14463 return 0;
14464 }
14465 else {
14466 return 1;
14467 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014468 }
14469 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014470 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014471 {
14472 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14473 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014474 if(not @Membs1
14475 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014476 { # private
14477 return 0;
14478 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014479 if($#Membs1!=$#Membs2)
14480 { # different number of elements
14481 return 1;
14482 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014483 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014484 {
14485 foreach my $Pos (@Membs1)
14486 { # compare elements by name and value
14487 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14488 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14489 { # different names
14490 return 1;
14491 }
14492 }
14493 }
14494 else
14495 {
14496 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014497 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014498 if($Level eq "Source")
14499 {
14500 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14501 { # different names
14502 return 1;
14503 }
14504 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014505
14506 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14507 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14508
14509 if($MT1{"Name"} ne $MT2{"Name"}
14510 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14511 {
14512 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14513 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14514
14515 if($PL1 ne $PL2)
14516 { # different pointer level
14517 return 1;
14518 }
14519
14520 # compare base types
14521 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14522 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14523
14524 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14525 { # different types
14526 return 1;
14527 }
14528 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014529 }
14530 }
14531 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014532 else
14533 {
14534 # TODO: arrays, etc.
14535 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014536 }
14537 return 0;
14538}
14539
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014540sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014541{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014542 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014543 if(not $Type1_Id or not $Type2_Id) {
14544 return ();
14545 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014546 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014547 my %Type1 = get_Type($Type1_Id, 1);
14548 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014549 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14550 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14551 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14552 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 +040014553
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014554 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14555 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014556 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14557 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14558 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14559 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14560 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14561 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14562 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014563 if($Type1{"Name"} eq $Type2{"Name"})
14564 {
14565 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14566 { # will be reported in mergeTypes() as typedef problem
14567 return ();
14568 }
14569 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14570 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14571 if(%Typedef_1 and %Typedef_2)
14572 {
14573 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14574 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14575 { # const Typedef
14576 return ();
14577 }
14578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014579 }
14580 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14581 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014582 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014583 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14584 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014585 {
14586 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14587 "Old_Value"=>$Type1_Base{"Name"},
14588 "New_Value"=>$Type2_Base{"Name"},
14589 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014590 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014591 }
14592 else
14593 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014594 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014595 { # format change
14596 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14597 "Old_Value"=>$Type1_Base{"Name"},
14598 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014599 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014600 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014601 }
14602 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14603 {
14604 %{$LocalProblems{$Prefix."_BaseType"}}=(
14605 "Old_Value"=>$Type1_Base{"Name"},
14606 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014607 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014608 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014609 }
14610 }
14611 }
14612 }
14613 elsif($Type1{"Name"} ne $Type2{"Name"})
14614 { # type change
14615 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14616 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014617 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014618 and $Type1_Pure{"Name"} eq "void")
14619 {
14620 %{$LocalProblems{"Return_Type_From_Void"}}=(
14621 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014622 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014623 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014624 elsif($Prefix eq "Return"
14625 and $Type2_Pure{"Name"} eq "void")
14626 {
14627 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14628 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014629 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014630 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014631 else
14632 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014633 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014634 and $Type1{"Size"} and $Type2{"Size"}
14635 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014636 {
14637 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14638 "Old_Value"=>$Type1{"Name"},
14639 "New_Value"=>$Type2{"Name"},
14640 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014641 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014642 }
14643 else
14644 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014645 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014646 { # format change
14647 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14648 "Old_Value"=>$Type1{"Name"},
14649 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014650 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014651 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014652 }
14653 elsif(tNameLock($Type1_Id, $Type2_Id))
14654 { # FIXME: correct this condition
14655 %{$LocalProblems{$Prefix."_Type"}}=(
14656 "Old_Value"=>$Type1{"Name"},
14657 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014658 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014659 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014660 }
14661 }
14662 }
14663 }
14664 }
14665 if($Type1_PLevel!=$Type2_PLevel)
14666 {
14667 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14668 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14669 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014670 if($Level eq "Source")
14671 {
14672 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014673 "Old_Value"=>$Type1_PLevel,
14674 "New_Value"=>$Type2_PLevel);
14675 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014676 else
14677 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014678 if($Type2_PLevel>$Type1_PLevel)
14679 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014680 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14681 "Old_Value"=>$Type1_PLevel,
14682 "New_Value"=>$Type2_PLevel);
14683 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014684 else
14685 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014686 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14687 "Old_Value"=>$Type1_PLevel,
14688 "New_Value"=>$Type2_PLevel);
14689 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014690 }
14691 }
14692 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014693 if($Type1_Pure{"Type"} eq "Array"
14694 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014695 { # base_type[N] -> base_type[N]
14696 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014697 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014698 foreach my $SubProblemType (keys(%SubProblems))
14699 {
14700 $SubProblemType=~s/_Type/_BaseType/g;
14701 next if(defined $LocalProblems{$SubProblemType});
14702 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14703 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14704 }
14705 }
14706 }
14707 return %LocalProblems;
14708}
14709
14710sub tNameLock($$)
14711{
14712 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014713 my $Changed = 0;
14714 if(differentDumps("G"))
14715 { # different GCC versions
14716 $Changed = 1;
14717 }
14718 elsif(differentDumps("V"))
14719 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014720 if(not checkDump(1, "2.20")
14721 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014722 { # latest names update
14723 # 2.6: added restrict qualifier
14724 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014725 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014726 $Changed = 1;
14727 }
14728 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014729
14730 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14731 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14732
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014733 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14734 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14735
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014736 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014737 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014738 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014739 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014740 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014741 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014742 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014743 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014744 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014745 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014746 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14747 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14748 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014749 { # equal base types
14750 return 0;
14751 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014752
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014753 if(not checkDump(1, "2.13")
14754 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014755 { # broken array names in ABI dumps < 2.13
14756 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014757 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014758 return 0;
14759 }
14760 }
14761
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014762 if(not checkDump(1, "2.6")
14763 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014764 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014765 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014766 and $TN2=~/\brestrict\b/) {
14767 return 0;
14768 }
14769 }
14770
14771 if(not checkDump(1, "2.20")
14772 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014773 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014774 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14775 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014776 return 0;
14777 }
14778 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014779 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014780 else
14781 {
14782 # typedef struct {...} type_t
14783 # typedef struct type_t {...} type_t
14784 if(index($TN1, " ".$TN2)!=-1)
14785 {
14786 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14787 return 0;
14788 }
14789 }
14790 if(index($TN2, " ".$TN1)!=-1)
14791 {
14792 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14793 return 0;
14794 }
14795 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014796
14797 if($TT1 eq "FuncPtr"
14798 and $TT2 eq "FuncPtr")
14799 {
14800 my $TN1_C = $TN1;
14801 my $TN2_C = $TN2;
14802
14803 $TN1_C=~s/\b(struct|union) //g;
14804 $TN2_C=~s/\b(struct|union) //g;
14805
14806 if($TN1_C eq $TN2_C) {
14807 return 0;
14808 }
14809 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014810 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014811
14812 my ($N1, $N2) = ($TN1, $TN2);
14813 $N1=~s/\b(struct|union) //g;
14814 $N2=~s/\b(struct|union) //g;
14815
14816 if($N1 eq $N2)
14817 { # QList<struct QUrl> and QList<QUrl>
14818 return 0;
14819 }
14820
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014821 return 1;
14822}
14823
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014824sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014825{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014826 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014827 if(defined $Cache{"differentDumps"}{$Check}) {
14828 return $Cache{"differentDumps"}{$Check};
14829 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014830 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014831 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014832 if($Check eq "G")
14833 {
14834 if(getGccVersion(1) ne getGccVersion(2))
14835 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014836 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014837 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014838 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014839 if($Check eq "V")
14840 {
14841 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14842 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14843 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014844 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014845 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014846 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014847 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014848 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014849}
14850
14851sub formatVersion($$)
14852{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014853 my ($V, $Digits) = @_;
14854 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014855 return join(".", splice(@Elems, 0, $Digits));
14856}
14857
14858sub htmlSpecChars($)
14859{
14860 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014861 if(not $Str) {
14862 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014864 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14865 $Str=~s/</&lt;/g;
14866 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
14867 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014868 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
14869 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014870 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014871 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014872 $Str=~s/\n/<br\/>/g;
14873 $Str=~s/\"/&quot;/g;
14874 $Str=~s/\'/&#39;/g;
14875 return $Str;
14876}
14877
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014878sub xmlSpecChars($)
14879{
14880 my $Str = $_[0];
14881 if(not $Str) {
14882 return $Str;
14883 }
14884
14885 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14886 $Str=~s/</&lt;/g;
14887 $Str=~s/>/&gt;/g;
14888
14889 $Str=~s/\"/&quot;/g;
14890 $Str=~s/\'/&#39;/g;
14891
14892 return $Str;
14893}
14894
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014895sub xmlSpecChars_R($)
14896{
14897 my $Str = $_[0];
14898 if(not $Str) {
14899 return $Str;
14900 }
14901
14902 $Str=~s/&amp;/&/g;
14903 $Str=~s/&lt;/</g;
14904 $Str=~s/&gt;/>/g;
14905
14906 $Str=~s/&quot;/"/g;
14907 $Str=~s/&#39;/'/g;
14908
14909 return $Str;
14910}
14911
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014912sub black_name($)
14913{
14914 my $Name = $_[0];
14915 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
14916}
14917
14918sub highLight_Signature($)
14919{
14920 my $Signature = $_[0];
14921 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
14922}
14923
14924sub highLight_Signature_Italic_Color($)
14925{
14926 my $Signature = $_[0];
14927 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
14928}
14929
14930sub separate_symbol($)
14931{
14932 my $Symbol = $_[0];
14933 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
14934 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
14935 ($Name, $Spec, $Ver) = ($1, $2, $3);
14936 }
14937 return ($Name, $Spec, $Ver);
14938}
14939
14940sub cut_f_attrs($)
14941{
14942 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
14943 return $2;
14944 }
14945 return "";
14946}
14947
14948sub highLight_Signature_PPos_Italic($$$$$)
14949{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014950 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
14951 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014952 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
14953 my $Return = "";
14954 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
14955 $Return = $2;
14956 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014957 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014958 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014959 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014960 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014961 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014962 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014963 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014964 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014965 }
14966 return $Signature;
14967 }
14968 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
14969 $Begin.=" " if($Begin!~/ \Z/);
14970 $End = cut_f_attrs($Signature);
14971 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014972 my ($Short, $Params) = split_Signature($Signature);
14973 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014974 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014975 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014976 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014977 $Part=~s/\A\s+|\s+\Z//g;
14978 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
14979 if($Part=~/\([\*]+(\w+)\)/i) {
14980 $ParamName = $1;#func-ptr
14981 }
14982 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
14983 $ParamName = $1;
14984 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014985 if(not $ParamName)
14986 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014987 push(@Parts, $Part_Styled);
14988 next;
14989 }
14990 if($ItalicParams and not $TName_Tid{1}{$Part}
14991 and not $TName_Tid{2}{$Part})
14992 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014993 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014994 if($Param_Pos ne ""
14995 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014996 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014997 }
14998 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014999 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015000 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015001 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015002 }
15003 $Part_Styled=~s/,(\w)/, $1/g;
15004 push(@Parts, $Part_Styled);
15005 }
15006 if(@Parts)
15007 {
15008 foreach my $Num (0 .. $#Parts)
15009 {
15010 if($Num==$#Parts)
15011 { # add ")" to the last parameter
15012 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15013 }
15014 elsif(length($Parts[$Num])<=45) {
15015 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15016 }
15017 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015018 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015019 }
15020 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015021 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015022 }
15023 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015024 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015025 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015026 $Signature=~s!\[\]![&#160;]!g;
15027 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015028 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15029 if($SymbolVersion) {
15030 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15031 }
15032 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015033}
15034
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015035sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015036{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015037 my $Signature = $_[0];
15038 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15039 {
15040 $Signature=~s/\A\Q$ShortName\E\(//g;
15041 cut_f_attrs($Signature);
15042 $Signature=~s/\)\Z//;
15043 return ($ShortName, $Signature);
15044 }
15045
15046 # error
15047 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015048}
15049
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015050sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015051{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015052 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015053 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015054 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15055 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015056 foreach my $Pos (0 .. length($Params) - 1)
15057 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015058 my $S = substr($Params, $Pos, 1);
15059 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015060 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015061 }
15062 if($S eq "," and
15063 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015064 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015065 if($Comma)
15066 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015067 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015068 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015069 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015070 }
15071 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015072 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015073 }
15074 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015075 if(not $Sp)
15076 { # remove spaces
15077 foreach (@Parts)
15078 {
15079 s/\A //g;
15080 s/ \Z//g;
15081 }
15082 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015083 return @Parts;
15084}
15085
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015086sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015087{
15088 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015089 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015090 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015091 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15092 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015093 $Center+=length($1);
15094 }
15095 foreach my $Pos (0 .. length($Sign)-1)
15096 {
15097 my $S = substr($Sign, $Pos, 1);
15098 if($S eq $Target)
15099 {
15100 if($B{"("}==$B{")"}
15101 and $B{"<"}==$B{">"}) {
15102 return $Center;
15103 }
15104 }
15105 if(defined $B{$S}) {
15106 $B{$S}+=1;
15107 }
15108 $Center+=1;
15109 }
15110 return 0;
15111}
15112
15113sub appendFile($$)
15114{
15115 my ($Path, $Content) = @_;
15116 return if(not $Path);
15117 if(my $Dir = get_dirname($Path)) {
15118 mkpath($Dir);
15119 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015120 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015121 print FILE $Content;
15122 close(FILE);
15123}
15124
15125sub writeFile($$)
15126{
15127 my ($Path, $Content) = @_;
15128 return if(not $Path);
15129 if(my $Dir = get_dirname($Path)) {
15130 mkpath($Dir);
15131 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015132 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015133 print FILE $Content;
15134 close(FILE);
15135}
15136
15137sub readFile($)
15138{
15139 my $Path = $_[0];
15140 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015141 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015142 local $/ = undef;
15143 my $Content = <FILE>;
15144 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015145 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015146 $Content=~s/\r/\n/g;
15147 }
15148 return $Content;
15149}
15150
15151sub get_filename($)
15152{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015153 if(defined $Cache{"get_filename"}{$_[0]}) {
15154 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015155 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015156 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15157 return ($Cache{"get_filename"}{$_[0]}=$1);
15158 }
15159 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015160}
15161
15162sub get_dirname($)
15163{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015164 if(defined $Cache{"get_dirname"}{$_[0]}) {
15165 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015166 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015167 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15168 return ($Cache{"get_dirname"}{$_[0]}=$1);
15169 }
15170 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015171}
15172
15173sub separate_path($) {
15174 return (get_dirname($_[0]), get_filename($_[0]));
15175}
15176
15177sub esc($)
15178{
15179 my $Str = $_[0];
15180 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15181 return $Str;
15182}
15183
15184sub readLineNum($$)
15185{
15186 my ($Path, $Num) = @_;
15187 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015188 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015189 foreach (1 ... $Num) {
15190 <FILE>;
15191 }
15192 my $Line = <FILE>;
15193 close(FILE);
15194 return $Line;
15195}
15196
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015197sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015198{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015199 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015200 return () if(not $Path or not -f $Path);
15201 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015202 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15203 {
15204 foreach my $AttrVal (split(/;/, $1))
15205 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015206 if($AttrVal=~/(.+):(.+)/)
15207 {
15208 my ($Name, $Value) = ($1, $2);
15209 $Attributes{$Name} = $Value;
15210 }
15211 }
15212 }
15213 return \%Attributes;
15214}
15215
15216sub is_abs($) {
15217 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15218}
15219
15220sub get_abs_path($)
15221{ # abs_path() should NOT be called for absolute inputs
15222 # because it can change them
15223 my $Path = $_[0];
15224 if(not is_abs($Path)) {
15225 $Path = abs_path($Path);
15226 }
15227 return $Path;
15228}
15229
15230sub get_OSgroup()
15231{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015232 my $N = $Config{"osname"};
15233 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015234 return "macos";
15235 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015236 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015237 return "bsd";
15238 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015239 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015240 return "beos";
15241 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015242 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015243 return "symbian";
15244 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015245 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015246 return "windows";
15247 }
15248 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015249 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015250 }
15251}
15252
15253sub getGccVersion($)
15254{
15255 my $LibVersion = $_[0];
15256 if($GCC_VERSION{$LibVersion})
15257 { # dump version
15258 return $GCC_VERSION{$LibVersion};
15259 }
15260 elsif($UsedDump{$LibVersion}{"V"})
15261 { # old-version dumps
15262 return "unknown";
15263 }
15264 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15265 if(not $GccVersion) {
15266 return "unknown";
15267 }
15268 return $GccVersion;
15269}
15270
15271sub showArch($)
15272{
15273 my $Arch = $_[0];
15274 if($Arch eq "arm"
15275 or $Arch eq "mips") {
15276 return uc($Arch);
15277 }
15278 return $Arch;
15279}
15280
15281sub getArch($)
15282{
15283 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015284
15285 if($TargetArch) {
15286 return $TargetArch;
15287 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015288 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015289 { # dump version
15290 return $CPU_ARCH{$LibVersion};
15291 }
15292 elsif($UsedDump{$LibVersion}{"V"})
15293 { # old-version dumps
15294 return "unknown";
15295 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015296
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015297 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015298}
15299
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015300sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015301{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015302 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015303
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015304 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015305 if(getArch(1) ne getArch(2)
15306 or getArch(1) eq "unknown"
15307 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015308 { # don't show architecture in the header
15309 $ArchInfo="";
15310 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015311 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015312 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015313 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015314 }
15315 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015316 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015317 }
15318 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015319 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015320 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015321
15322 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15323 {
15324 my $M1 = $UsedDump{1}{"M"};
15325 my $M2 = $UsedDump{2}{"M"};
15326
15327 if($M1 eq $M2)
15328 {
15329 $Title .= " report for the <span style='color:Blue;'>$M1</span> object";
15330 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15331 }
15332 else
15333 {
15334 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$Descriptor{1}{"Version"}."</span>)";
15335 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$Descriptor{2}{"Version"}."</span>) objects";
15336 }
15337 }
15338 else
15339 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015340 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015341 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15342 }
15343
15344 $Title .= $ArchInfo;
15345
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015346 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015347 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015348 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015349 $Title = "<h1>".$Title."</h1>\n";
15350 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015351}
15352
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015353sub get_CheckedHeaders($)
15354{
15355 my $LibVersion = $_[0];
15356
15357 my @Headers = ();
15358
15359 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15360 {
15361 my $File = get_filename($Path);
15362 if(not is_target_header($File, $LibVersion)) {
15363 next;
15364 }
15365
15366 if(skipHeader($File, $LibVersion)) {
15367 next;
15368 }
15369
15370 push(@Headers, $Path);
15371 }
15372
15373 return @Headers;
15374}
15375
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015376sub get_SourceInfo()
15377{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015378 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015379
15380 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015381 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015382 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15383 $CheckedHeaders .= "<div class='h_list'>\n";
15384 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 +040015385 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015386 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15387 my $Name = get_filename($Identity);
15388 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15389 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015390 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015391 $CheckedHeaders .= "</div>\n";
15392 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015393 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015394
15395 if(my @Sources = keys(%{$Registered_Sources{1}}))
15396 {
15397 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15398 $CheckedSources .= "<div class='h_list'>\n";
15399 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15400 {
15401 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15402 my $Name = get_filename($Identity);
15403 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15404 $CheckedSources .= $Name.$Comment."<br/>\n";
15405 }
15406 $CheckedSources .= "</div>\n";
15407 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15408 }
15409
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015410 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015411 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015412 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015413 $CheckedLibs .= "<div class='lib_list'>\n";
15414 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15415 {
15416 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15417 $CheckedLibs .= $Library."<br/>\n";
15418 }
15419 $CheckedLibs .= "</div>\n";
15420 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015421 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015422
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015423 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15424}
15425
15426sub get_ObjTitle()
15427{
15428 if(defined $UsedDump{1}{"DWARF"}) {
15429 return "Objects";
15430 }
15431 else {
15432 return ucfirst($SLIB_TYPE)." Libraries";
15433 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015434}
15435
15436sub get_TypeProblems_Count($$$)
15437{
15438 my ($TypeChanges, $TargetPriority, $Level) = @_;
15439 my $Type_Problems_Count = 0;
15440 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15441 {
15442 my %Kinds_Target = ();
15443 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15444 {
15445 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15446 {
15447 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015448 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15449 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015450 if($Kinds_Target{$Kind}{$Target}) {
15451 next;
15452 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015453
15454 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15455 {
15456 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15457 { # select a problem with the highest priority
15458 next;
15459 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015460 }
15461 $Kinds_Target{$Kind}{$Target} = 1;
15462 $Type_Problems_Count += 1;
15463 }
15464 }
15465 }
15466 return $Type_Problems_Count;
15467}
15468
15469sub get_Summary($)
15470{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015471 my $Level = $_[0];
15472 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015473 $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 +040015474 %{$RESULT{$Level}} = (
15475 "Problems"=>0,
15476 "Warnings"=>0,
15477 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015478 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015479 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015480 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015481 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015482 {
15483 if(not defined $CompatRules{$Level}{$Kind})
15484 { # unknown rule
15485 if(not $UnknownRules{$Level}{$Kind})
15486 { # only one warning
15487 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15488 $UnknownRules{$Level}{$Kind}=1;
15489 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015490 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015491 }
15492 }
15493 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015494 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15495 {
15496 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15497 {
15498 if(not defined $CompatRules{$Level}{$Kind})
15499 { # unknown rule
15500 if(not $UnknownRules{$Level}{$Kind})
15501 { # only one warning
15502 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15503 $UnknownRules{$Level}{$Kind}=1;
15504 }
15505 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15506 }
15507 }
15508 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015509 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015510 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015511 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015512 {
15513 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15514 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015515 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015516 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015517 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015518 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015519 $Added += 1;
15520 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015521 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015522 {
15523 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015524 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015525 }
15526 else
15527 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015528 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015529 $I_Other += 1;
15530 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015531 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015532 $I_Problems_High += 1;
15533 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015534 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015535 $I_Problems_Medium += 1;
15536 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015537 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015538 $I_Problems_Low += 1;
15539 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015540 if(($Severity ne "Low" or $StrictCompat)
15541 and $Severity ne "Safe") {
15542 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015543 }
15544 }
15545 }
15546 }
15547 }
15548 }
15549 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015550 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015551 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015552 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015553 {
15554 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15555 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015556 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015557 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015558 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15559 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015560 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015561 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15562
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015563 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015564 { # select a problem with the highest priority
15565 next;
15566 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015567
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015568 if(($Severity ne "Low" or $StrictCompat)
15569 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015570 {
15571 if(defined $TotalAffected{$Level}{$Interface})
15572 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015573 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15574 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015575 }
15576 }
15577 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015578 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015580 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015581
15582 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15583
15584 if($MaxSeverity)
15585 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015586 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15587 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015588 }
15589 }
15590 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015591 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015592 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015593 }
15594 }
15595 }
15596 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015597
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015598 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15599 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15600 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15601 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015602
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015603 %TypeChanges = (); # free memory
15604
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015605 # changed and removed public symbols
15606 my $SCount = keys(%{$CheckedSymbols{$Level}});
15607 if($ExtendedCheck)
15608 { # don't count external_func_0 for constants
15609 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015610 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015611 if($SCount)
15612 {
15613 my %Weight = (
15614 "High" => 100,
15615 "Medium" => 50,
15616 "Low" => 25
15617 );
15618 foreach (keys(%{$TotalAffected{$Level}})) {
15619 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015620 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015621 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015622 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015623 else {
15624 $RESULT{$Level}{"Affected"} = 0;
15625 }
15626
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015627 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15628 if($RESULT{$Level}{"Affected"}>=100) {
15629 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015630 }
15631
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015632 $RESULT{$Level}{"Problems"} += $Removed;
15633 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015634 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015635 if($StrictCompat) {
15636 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15637 }
15638 else {
15639 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15640 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015641
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015642 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015643 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015644 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015645 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015646 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015647 if($Severity eq "Safe")
15648 {
15649 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015650 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015651 elsif($Severity eq "Low")
15652 {
15653 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015654 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015655 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015656 }
15657
15658 if($C_Problems_Low)
15659 {
15660 if($StrictCompat) {
15661 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15662 }
15663 else {
15664 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015665 }
15666 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015667 if($RESULT{$Level}{"Problems"}
15668 and $RESULT{$Level}{"Affected"}) {
15669 $RESULT{$Level}{"Verdict"} = "incompatible";
15670 }
15671 else {
15672 $RESULT{$Level}{"Verdict"} = "compatible";
15673 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015674
15675 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15676 if(not $TotalTypes)
15677 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015678 $TotalTypes = keys(%{$TName_Tid{1}});
15679 }
15680
15681 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15682 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15683
15684 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15685
15686 if($ReportFormat eq "xml")
15687 { # XML
15688 # test info
15689 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15690 $TestInfo .= " <version1>\n";
15691 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015692 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015693 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15694 $TestInfo .= " </version1>\n";
15695
15696 $TestInfo .= " <version2>\n";
15697 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015698 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015699 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15700 $TestInfo .= " </version2>\n";
15701 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15702
15703 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015704 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015705 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015706 $TestResults .= " <headers>\n";
15707 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15708 {
15709 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15710 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15711 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15712 }
15713 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015714 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015715
15716 if(my @Sources = keys(%{$Registered_Sources{1}}))
15717 {
15718 $TestResults .= " <sources>\n";
15719 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15720 {
15721 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15722 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15723 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15724 }
15725 $TestResults .= " </sources>\n";
15726 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015727
15728 $TestResults .= " <libs>\n";
15729 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15730 {
15731 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15732 $TestResults .= " <name>$Library</name>\n";
15733 }
15734 $TestResults .= " </libs>\n";
15735
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015736 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015737 $TestResults .= " <types>".$TotalTypes."</types>\n";
15738
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015739 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15740 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015741 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15742
15743 # problem summary
15744 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15745 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15746
15747 $Problem_Summary .= " <problems_with_types>\n";
15748 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15749 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15750 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15751 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15752 $Problem_Summary .= " </problems_with_types>\n";
15753
15754 $Problem_Summary .= " <problems_with_symbols>\n";
15755 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15756 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15757 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015758 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015759 $Problem_Summary .= " </problems_with_symbols>\n";
15760
15761 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015762 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015763 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015764
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015765 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15766
15767 return ($TestInfo.$TestResults.$Problem_Summary, "");
15768 }
15769 else
15770 { # HTML
15771 # test info
15772 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015773 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015774 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetTitle</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015775
15776 my (@VInf1, @VInf2, $AddTestInfo) = ();
15777 if($Arch1 ne "unknown"
15778 and $Arch2 ne "unknown")
15779 { # CPU arch
15780 if($Arch1 eq $Arch2)
15781 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015782 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015783 }
15784 else
15785 { # go to the version number
15786 push(@VInf1, showArch($Arch1));
15787 push(@VInf2, showArch($Arch2));
15788 }
15789 }
15790 if($GccV1 ne "unknown"
15791 and $GccV2 ne "unknown"
15792 and $OStarget ne "windows")
15793 { # GCC version
15794 if($GccV1 eq $GccV2)
15795 { # go to the separate section
15796 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15797 }
15798 else
15799 { # go to the version number
15800 push(@VInf1, "gcc ".$GccV1);
15801 push(@VInf2, "gcc ".$GccV2);
15802 }
15803 }
15804 # show long version names with GCC version and CPU architecture name (if different)
15805 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15806 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15807 $TestInfo .= $AddTestInfo;
15808 #if($COMMON_LANGUAGE{1}) {
15809 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15810 #}
15811 if($ExtendedCheck) {
15812 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15813 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015814 if($JoinReport)
15815 {
15816 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015817 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015818 }
15819 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015820 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015821 }
15822 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015823 $TestInfo .= "</table>\n";
15824
15825 # test results
15826 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015827 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015828
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030015829 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015830 {
15831 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15832 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15833 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015834
15835 if(my @Sources = keys(%{$Registered_Sources{1}}))
15836 {
15837 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15838 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15839 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015840
15841 if(not $ExtendedCheck)
15842 {
15843 my $Libs_Link = "0";
15844 $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 +040015845 $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 +040015846 }
15847
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015848 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015849
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015850 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015851 if($JoinReport) {
15852 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15853 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015854 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015855 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015856 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15857 }
15858 else {
15859 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15860 }
15861 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015862 $TestResults .= "</table>\n";
15863
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015864 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015865 # problem summary
15866 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015867 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015868 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15869
15870 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015871 if($Added>0)
15872 {
15873 if($JoinReport) {
15874 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15875 }
15876 else {
15877 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15878 }
15879 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015880 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015881 $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 +040015882
15883 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015884 if($Removed>0)
15885 {
15886 if($JoinReport) {
15887 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15888 }
15889 else {
15890 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
15891 }
15892 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015893 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015894 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
15895 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015896
15897 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015898 $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 +040015899 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015900 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
15901 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015902
15903 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015904 $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 +040015905 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015906 $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 +040015907
15908 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015909 $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 +040015910 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015911 $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 +040015912
15913 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015914 $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 +040015915 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015916 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
15917 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015918
15919 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015920 $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 +040015921 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015922 $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 +040015923
15924 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015925 $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 +040015926 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015927 $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 +040015928
15929 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015930 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
15931 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015932 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015933 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015934 $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 +040015935
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015936 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015937 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015938 {
15939 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015940 $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 +040015941 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015942
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015943 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015944 {
15945 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015946 $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 +040015947 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015948
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015949 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015950 {
15951 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
15952 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
15953 }
15954
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015955 $META_DATA .= "tool_version:$TOOL_VERSION";
15956 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015957 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015958 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
15959 }
15960}
15961
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015962sub getStyle($$$)
15963{
15964 my ($Subj, $Act, $Num) = @_;
15965 my %Style = (
15966 "A"=>"new",
15967 "R"=>"failed",
15968 "S"=>"passed",
15969 "L"=>"warning",
15970 "M"=>"failed",
15971 "H"=>"failed"
15972 );
15973 if($Num>0) {
15974 return " class='".$Style{$Act}."'";
15975 }
15976 return "";
15977}
15978
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015979sub show_number($)
15980{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015981 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015982 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015983 my $Num = cut_off_number($_[0], 2, 0);
15984 if($Num eq "0")
15985 {
15986 foreach my $P (3 .. 7)
15987 {
15988 $Num = cut_off_number($_[0], $P, 1);
15989 if($Num ne "0") {
15990 last;
15991 }
15992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015993 }
15994 if($Num eq "0") {
15995 $Num = $_[0];
15996 }
15997 return $Num;
15998 }
15999 return $_[0];
16000}
16001
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016002sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016003{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016004 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016005 if($num!~/\./)
16006 {
16007 $num .= ".";
16008 foreach (1 .. $digs_to_cut-1) {
16009 $num .= "0";
16010 }
16011 }
16012 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16013 {
16014 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16015 $num .= "0";
16016 }
16017 }
16018 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16019 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16020 }
16021 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016022 if($z) {
16023 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16024 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016025 return $num;
16026}
16027
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016028sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016029{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016030 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016031 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016032
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016033 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016034 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16035 {
16036 my $Header = $Constants{1}{$Constant}{"Header"};
16037 if(not $Header)
16038 { # added
16039 $Header = $Constants{2}{$Constant}{"Header"}
16040 }
16041
16042 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16043 {
16044 if(not defined $CompatRules{$Level}{$Kind}) {
16045 next;
16046 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016047 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016048 next;
16049 }
16050 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16051 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016052 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016053
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016054 if($ReportFormat eq "xml")
16055 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016056 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016057 {
16058 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016059 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016060 {
16061 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016062 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16063 {
16064 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16065 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16066 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016067
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016068 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16069 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16070 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016071 if($Overcome) {
16072 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16073 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016074 $CHANGED_CONSTANTS .= " </problem>\n";
16075 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016076 $CHANGED_CONSTANTS .= " </constant>\n";
16077 }
16078 $CHANGED_CONSTANTS .= " </header>\n";
16079 }
16080 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16081 }
16082 else
16083 { # HTML
16084 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016085 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016086 {
16087 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016088 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016089 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016090 my $Report = "";
16091
16092 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16093 {
16094 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16095 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16096 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16097 $Number += 1;
16098 }
16099 if($Report)
16100 {
16101 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16102 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16103 $Report = insertIDs($Report);
16104 }
16105 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016106 }
16107 $CHANGED_CONSTANTS .= "<br/>\n";
16108 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016109 if($CHANGED_CONSTANTS)
16110 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016111 my $Title = "Problems with Constants, $TargetSeverity Severity";
16112 if($TargetSeverity eq "Safe")
16113 { # Safe Changes
16114 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016115 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016116 $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 +040016117 }
16118 }
16119 return $CHANGED_CONSTANTS;
16120}
16121
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016122sub getTitle($$$)
16123{
16124 my ($Header, $Library, $NameSpace) = @_;
16125 my $Title = "";
16126 if($Library and $Library!~/\.\w+\Z/) {
16127 $Library .= " (.$LIB_EXT)";
16128 }
16129 if($Header and $Library)
16130 {
16131 $Title .= "<span class='h_name'>$Header</span>";
16132 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16133 }
16134 elsif($Library) {
16135 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16136 }
16137 elsif($Header) {
16138 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16139 }
16140 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016141 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016142 }
16143 return $Title;
16144}
16145
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016146sub get_Report_Added($)
16147{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016148 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016149 my $ADDED_INTERFACES = "";
16150 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016151 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016152 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016153 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016154 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016155 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016156 {
16157 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16158 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016159 if($Level eq "Source" and $ReportFormat eq "html")
16160 { # do not show library name in HTML report
16161 $DyLib = "";
16162 }
16163 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016164 }
16165 }
16166 }
16167 if($ReportFormat eq "xml")
16168 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016169 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016170 {
16171 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016172 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016173 {
16174 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016175 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016176 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16177 }
16178 $ADDED_INTERFACES .= " </library>\n";
16179 }
16180 $ADDED_INTERFACES .= " </header>\n";
16181 }
16182 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16183 }
16184 else
16185 { # HTML
16186 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016187 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016188 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016189 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016190 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016191 my %NameSpaceSymbols = ();
16192 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016193 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016194 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016195 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016196 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016197 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16198 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016199 foreach my $Interface (@SortedInterfaces)
16200 {
16201 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016202 my $Signature = get_Signature($Interface, 2);
16203 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016204 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016205 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016206 if($Interface=~/\A(_Z|\?)/)
16207 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016208 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016209 $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 +040016210 }
16211 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016212 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016213 }
16214 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016215 else
16216 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016217 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016218 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016219 }
16220 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016221 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016222 }
16223 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016224 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016225 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016226 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016227 }
16228 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016229 if($ADDED_INTERFACES)
16230 {
16231 my $Anchor = "<a name='Added'></a>";
16232 if($JoinReport) {
16233 $Anchor = "<a name='".$Level."_Added'></a>";
16234 }
16235 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016236 }
16237 }
16238 return $ADDED_INTERFACES;
16239}
16240
16241sub get_Report_Removed($)
16242{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016243 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016244 my $REMOVED_INTERFACES = "";
16245 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016246 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016247 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016248 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016249 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016250 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016251 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016252 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16253 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016254 if($Level eq "Source" and $ReportFormat eq "html")
16255 { # do not show library name in HTML report
16256 $DyLib = "";
16257 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016258 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016259 }
16260 }
16261 }
16262 if($ReportFormat eq "xml")
16263 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016264 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016265 {
16266 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016267 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016268 {
16269 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016270 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16271 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016272 }
16273 $REMOVED_INTERFACES .= " </library>\n";
16274 }
16275 $REMOVED_INTERFACES .= " </header>\n";
16276 }
16277 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16278 }
16279 else
16280 { # HTML
16281 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016282 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016283 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016284 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016285 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016286 my %NameSpaceSymbols = ();
16287 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016288 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016289 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016290 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016291 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016292 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16293 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016294 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016295 {
16296 $Removed_Number += 1;
16297 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016298 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016299 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016300 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016301 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016302 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016303 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016304 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016305 $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 +040016306 }
16307 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016308 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016309 }
16310 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016311 else
16312 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016313 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016314 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016315 }
16316 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016317 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016318 }
16319 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016320 }
16321 }
16322 $REMOVED_INTERFACES .= "<br/>\n";
16323 }
16324 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016325 if($REMOVED_INTERFACES)
16326 {
16327 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16328 if($JoinReport) {
16329 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16330 }
16331 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016332 }
16333 }
16334 return $REMOVED_INTERFACES;
16335}
16336
16337sub getXmlParams($$)
16338{
16339 my ($Content, $Problem) = @_;
16340 return "" if(not $Content or not $Problem);
16341 my %XMLparams = ();
16342 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16343 {
16344 my $Macro = "\@".lc($Attr);
16345 if($Content=~/\Q$Macro\E/) {
16346 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16347 }
16348 }
16349 my @PString = ();
16350 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016351 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016352 }
16353 if(@PString) {
16354 return " ".join(" ", @PString);
16355 }
16356 else {
16357 return "";
16358 }
16359}
16360
16361sub addMarkup($)
16362{
16363 my $Content = $_[0];
16364 # auto-markup
16365 $Content=~s/\n[ ]*//; # spaces
16366 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16367 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016368 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016369 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16370 if($Content=~/\ANOTE:/)
16371 { # notes
16372 $Content=~s!(NOTE):!<b>$1</b>:!g;
16373 }
16374 else {
16375 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16376 }
16377 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16378 my @Keywords = (
16379 "void",
16380 "const",
16381 "static",
16382 "restrict",
16383 "volatile",
16384 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016385 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016386 );
16387 my $MKeys = join("|", @Keywords);
16388 foreach (@Keywords) {
16389 $MKeys .= "|non-".$_;
16390 }
16391 $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 +040016392
16393 # Markdown
16394 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16395 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016396 return $Content;
16397}
16398
16399sub applyMacroses($$$$)
16400{
16401 my ($Level, $Kind, $Content, $Problem) = @_;
16402 return "" if(not $Content or not $Problem);
16403 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16404 $Content = addMarkup($Content);
16405 # macros
16406 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16407 {
16408 my $Macro = "\@".lc($Attr);
16409 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016410 if(not defined $Value
16411 or $Value eq "") {
16412 next;
16413 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016414
16415 if(index($Content, $Macro)==-1) {
16416 next;
16417 }
16418
16419 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16420 and $Kind!~/_Type_/
16421 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016422 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016423 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016424 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016425 $Value = black_name($Value);
16426 }
16427 elsif($Value=~/\s/) {
16428 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16429 }
16430 elsif($Value=~/\A\d+\Z/
16431 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16432 { # bits to bytes
16433 if($Value % $BYTE_SIZE)
16434 { # bits
16435 if($Value==1) {
16436 $Value = "<b>".$Value."</b> bit";
16437 }
16438 else {
16439 $Value = "<b>".$Value."</b> bits";
16440 }
16441 }
16442 else
16443 { # bytes
16444 $Value /= $BYTE_SIZE;
16445 if($Value==1) {
16446 $Value = "<b>".$Value."</b> byte";
16447 }
16448 else {
16449 $Value = "<b>".$Value."</b> bytes";
16450 }
16451 }
16452 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016453 else
16454 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016455 $Value = "<b>".htmlSpecChars($Value)."</b>";
16456 }
16457 $Content=~s/\Q$Macro\E/$Value/g;
16458 }
16459
16460 if($Content=~/(\A|[^\@\w])\@\w/)
16461 {
16462 if(not $IncompleteRules{$Level}{$Kind})
16463 { # only one warning
16464 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16465 $IncompleteRules{$Level}{$Kind} = 1;
16466 }
16467 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016468 return $Content;
16469}
16470
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016471sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016472{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016473 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016474 my $INTERFACE_PROBLEMS = "";
16475 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016476
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016477 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016478 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016479 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16480 if($SV and defined $CompatProblems{$Level}{$SN}) {
16481 next;
16482 }
16483 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016484 {
16485 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016486 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016487 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016488 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16489 my $DyLib = $Symbol_Library{1}{$Symbol};
16490 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016491 { # Symbol with Version
16492 $DyLib = $Symbol_Library{1}{$VSym};
16493 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016494 if(not $DyLib)
16495 { # const global data
16496 $DyLib = "";
16497 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016498 if($Level eq "Source" and $ReportFormat eq "html")
16499 { # do not show library name in HTML report
16500 $DyLib = "";
16501 }
16502 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16503 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016504 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016505 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16506 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016507 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016508 }
16509 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016510 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16511 {
16512 delete($SymbolChanges{$Symbol}{$Kind});
16513 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016514 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016515 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016516 }
16517 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016518 if(not keys(%{$SymbolChanges{$Symbol}})) {
16519 delete($SymbolChanges{$Symbol});
16520 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016521 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016522
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016523 if($ReportFormat eq "xml")
16524 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016525 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016526 {
16527 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016528 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016529 {
16530 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016531 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16532 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016533 {
16534 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16535 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16536 {
16537 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16538 {
16539 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016540 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016541
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016542 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16543 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16544 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16545 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16546 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016547 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16548 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16549 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016550 $INTERFACE_PROBLEMS .= " </problem>\n";
16551 }
16552 }
16553 $INTERFACE_PROBLEMS .= " </symbol>\n";
16554 }
16555 $INTERFACE_PROBLEMS .= " </library>\n";
16556 }
16557 $INTERFACE_PROBLEMS .= " </header>\n";
16558 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016559 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016560 }
16561 else
16562 { # HTML
16563 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016564 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016565 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016566 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016567 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016568 my (%NameSpaceSymbols, %NewSignature) = ();
16569 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016570 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016571 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016572 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016573 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016574 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016575 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 +040016576 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016577 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016578 my $Signature = get_Signature($Symbol, 1);
16579 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016580 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016581 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016582 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016583 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016584 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016585 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016586 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016587 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016588 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016589 }
16590 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16591 {
16592 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016593 $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 +040016594 $ProblemNum += 1;
16595 $ProblemsNum += 1;
16596 }
16597 }
16598 }
16599 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016600 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016601 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016602 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016603 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016604 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016605 }
16606 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016607 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016608 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016609 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16610 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16611 if($NewSignature{$Symbol})
16612 { # argument list changed to
16613 $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 +040016614 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016615 if($Symbol=~/\A(_Z|\?)/) {
16616 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16617 }
16618 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16619 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016620 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016621 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016622 }
16623 }
16624 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016625 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016626 }
16627 }
16628 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016629
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016630 if($INTERFACE_PROBLEMS)
16631 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016632 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16633 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16634 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016635 { # Safe Changes
16636 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016637 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016638 $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 +040016639 }
16640 }
16641 return $INTERFACE_PROBLEMS;
16642}
16643
16644sub get_Report_TypeProblems($$)
16645{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016646 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016647 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016648 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016649
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016650 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016651 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016652 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016653 {
16654 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16655 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016656 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016657 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016658 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016659 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016660 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016661
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016662 if($Severity eq "Safe"
16663 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016664 next;
16665 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016666
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016667 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16668 {
16669 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16670 { # select a problem with the highest priority
16671 next;
16672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016673 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016674
16675 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016676 }
16677 }
16678 }
16679 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016680
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016681 my %Kinds_Locations = ();
16682 foreach my $TypeName (keys(%TypeChanges))
16683 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016684 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016685 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16686 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016687 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016688 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016689 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016690 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016691 { # other priority
16692 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16693 next;
16694 }
16695 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16696 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016697 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016698 { # duplicate target
16699 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16700 next;
16701 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016702 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016703 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016704 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016705 }
16706 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16707 delete($TypeChanges{$TypeName}{$Kind});
16708 }
16709 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016710 if(not keys(%{$TypeChanges{$TypeName}})) {
16711 delete($TypeChanges{$TypeName});
16712 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016713 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016714
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016715 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 +040016716 if($ReportFormat eq "xml")
16717 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016718 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016719 {
16720 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016721 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016722 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016723 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016724 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16725 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016726 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016727 {
16728 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16729 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16730 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16731 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16732 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16733 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016734 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16735 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16736 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016737 $TYPE_PROBLEMS .= " </problem>\n";
16738 }
16739 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016740 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016741 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016742 $TYPE_PROBLEMS .= showVTables($TypeName);
16743 }
16744 $TYPE_PROBLEMS .= " </type>\n";
16745 }
16746 $TYPE_PROBLEMS .= " </header>\n";
16747 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016748 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016749 }
16750 else
16751 { # HTML
16752 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016753 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016754 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016755 my (%NameSpace_Type) = ();
16756 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016757 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016758 }
16759 foreach my $NameSpace (sort keys(%NameSpace_Type))
16760 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016761 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016762 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 +040016763 foreach my $TypeName (@SortedTypes)
16764 {
16765 my $ProblemNum = 1;
16766 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016767
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016768 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16769 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016770 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016771 {
16772 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16773 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16774 {
16775 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
16776 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16777 $ProblemNum += 1;
16778 $ProblemsNum += 1;
16779 }
16780 }
16781 }
16782 $ProblemNum -= 1;
16783 if($TYPE_REPORT)
16784 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016785 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016786 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016787 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016788 $ShowVTables = showVTables($TypeName);
16789 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016790
16791 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016792 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16793 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16794 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16795 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016796 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016797 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016798 }
16799 }
16800 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016801 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016802 }
16803 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016804
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016805 if($TYPE_PROBLEMS)
16806 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016807 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16808 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016809 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016810 { # Safe Changes
16811 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016812 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016813 $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 +040016814 }
16815 }
16816 return $TYPE_PROBLEMS;
16817}
16818
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016819sub show_Type($$$)
16820{
16821 my ($Name, $Html, $LibVersion) = @_;
16822 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16823 $TType = lc($TType);
16824 if($TType=~/struct|union|enum/) {
16825 $Name=~s/\A\Q$TType\E //g;
16826 }
16827 if($Html) {
16828 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16829 }
16830 else {
16831 $Name = $TType." ".$Name;
16832 }
16833 return $Name;
16834}
16835
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016836sub get_Anchor($$$)
16837{
16838 my ($Kind, $Level, $Severity) = @_;
16839 if($JoinReport)
16840 {
16841 if($Severity eq "Safe") {
16842 return "Other_".$Level."_Changes_In_".$Kind."s";
16843 }
16844 else {
16845 return $Kind."_".$Level."_Problems_".$Severity;
16846 }
16847 }
16848 else
16849 {
16850 if($Severity eq "Safe") {
16851 return "Other_Changes_In_".$Kind."s";
16852 }
16853 else {
16854 return $Kind."_Problems_".$Severity;
16855 }
16856 }
16857}
16858
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016859sub showVTables($)
16860{
16861 my $TypeName = $_[0];
16862 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016863 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016864 if(defined $Type1{"VTable"}
16865 and keys(%{$Type1{"VTable"}}))
16866 {
16867 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016868 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016869 if(defined $Type2{"VTable"}
16870 and keys(%{$Type2{"VTable"}}))
16871 {
16872 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
16873 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016874 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016875 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016876 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
16877 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016878 }
16879 my $VTABLES = "";
16880 if($ReportFormat eq "xml")
16881 { # XML
16882 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016883 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016884 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016885 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016886 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
16887 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016888 $VTABLES .= " </entry>\n";
16889 }
16890 $VTABLES .= " </vtable>\n\n";
16891 }
16892 else
16893 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016894 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016895 $VTABLES .= "<tr><th>Offset</th>";
16896 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016897 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016898 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016899 {
16900 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016901 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016902 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016903 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016904 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016905 $Color1 = " class='failed'";
16906 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016907 }
16908 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016909 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016910 }
16911 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016912 $VTABLES .= "<tr><th>".$Index."</th>\n";
16913 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
16914 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016915 }
16916 $VTABLES .= "</table><br/>\n";
16917 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016918 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016919 }
16920 return $VTABLES;
16921 }
16922 }
16923 return "";
16924}
16925
16926sub simpleVEntry($)
16927{
16928 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016929 if(not defined $VEntry
16930 or $VEntry eq "") {
16931 return "";
16932 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016933
16934 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016935 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
16936 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
16937 if($VEntry=~/\A_ZThn.+\Z/) {
16938 $VEntry = "non-virtual thunk";
16939 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016940 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016941 # support for old GCC versions
16942 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
16943 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
16944 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016945 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
16946 return $VEntry;
16947}
16948
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016949sub adjustParamPos($$$)
16950{
16951 my ($Pos, $Symbol, $LibVersion) = @_;
16952 if(defined $CompleteSignature{$LibVersion}{$Symbol})
16953 {
16954 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
16955 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
16956 {
16957 return $Pos-1;
16958 }
16959
16960 return $Pos;
16961 }
16962
16963 return undef;
16964}
16965
16966sub getParamPos($$$)
16967{
16968 my ($Name, $Symbol, $LibVersion) = @_;
16969
16970 if(defined $CompleteSignature{$LibVersion}{$Symbol}
16971 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
16972 {
16973 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
16974 foreach (keys(%{$Info->{"Param"}}))
16975 {
16976 if($Info->{"Param"}{$_}{"name"} eq $Name)
16977 {
16978 return $_;
16979 }
16980 }
16981 }
16982
16983 return undef;
16984}
16985
16986sub getParamName($)
16987{
16988 my $Loc = $_[0];
16989 $Loc=~s/\->.*//g;
16990 return $Loc;
16991}
16992
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016993sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016994{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016995 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016996 my $LIMIT = 10;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016997
16998 if(defined $AffectLimit)
16999 {
17000 $LIMIT = $AffectLimit;
17001 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017002
17003 my %SymSel = ();
17004 my %SymLocKind = ();
17005
17006 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017007 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017008 if(index($Symbol, "_Z")==0
17009 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017010 { # duplicated problems for C2 constructors, D2 and D0 destructors
17011 next;
17012 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017013
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017014 foreach my $Kind (sort keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017015 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017016 if(not defined $CompatProblems{$Level}{$Symbol}
17017 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17018 next;
17019 }
17020
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017021 foreach my $Loc (sort keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017022 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017023 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017024 next;
17025 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017026
17027 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17028 if($Level eq "Source")
17029 { # remove symbol version
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017030 $Symbol = $SN;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017031 }
17032
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017033 if($SV and defined $CompatProblems{$Level}{$SN}
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017034 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017035 { # duplicated problems for versioned symbols
17036 next;
17037 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017038
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017039 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017040 if($Type_Name ne $Target_TypeName) {
17041 next;
17042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017043
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017044 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017045 }
17046 }
17047 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017048
17049 foreach my $Symbol (sort keys(%SymLocKind))
17050 {
17051 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17052 {
17053 foreach my $Kind (keys(%{$SymLocKind{$Symbol}{$Loc}}))
17054 {
17055 $SymSel{$Symbol}{"Loc"} = $Loc;
17056 $SymSel{$Symbol}{"Kind"} = $Kind;
17057
17058 last LOOP;
17059 }
17060 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017061 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017062
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017063 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017064 my $Num = 0;
17065
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017066 if($ReportFormat eq "xml")
17067 { # XML
17068 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017069
17070 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017071 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017072 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017073 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017074 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017075
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017076 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017077 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017078 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017079 $Target .= " param=\"$PName\"";
17080 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017081 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017082 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017083 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017084 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017085 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017086 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017087 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017088
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017089 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017090 $Target .= " field=\"$1\"";
17091 }
17092
17093 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017094 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017095 $Affected .= " </symbol>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017096
17097 if($Num>$LIMIT) {
17098 last LOOP;
17099 }
17100
17101 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017102 }
17103 $Affected .= " </affected>\n";
17104 }
17105 else
17106 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017107 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017108 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017109 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17110 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017111 my $PName = getParamName($SymSel{$Symbol}{"Loc"});
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017112 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17113
17114 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>";
17115 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
17116
17117 if($Num>$LIMIT) {
17118 last;
17119 }
17120
17121 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017122 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017123
17124 if(keys(%SymSel)>$LIMIT) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017125 $Affected .= " ...<br/>"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017126 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017127
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017128 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017129 if($Affected)
17130 {
17131 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017132 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymSel).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017133 }
17134 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017135
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017136 return $Affected;
17137}
17138
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017139sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017140{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017141 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017142 if($L2=~/\A(retval|this)\b/
17143 and $L1!~/\A(retval|this)\b/)
17144 {
17145 if($L1!~/\-\>/) {
17146 return 1;
17147 }
17148 elsif($L2=~/\-\>/) {
17149 return 1;
17150 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017151 }
17152 return 0;
17153}
17154
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017155sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017156{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017157 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017158
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017159 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017160
17161 my $Location_I = $Location;
17162 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17163
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017164 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017165
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017166 if($Kind eq "Overridden_Virtual_Method"
17167 or $Kind eq "Overridden_Virtual_Method_B") {
17168 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17169 }
17170 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17171 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017172 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17173
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017174 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17175 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017176 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17177 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17178
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017179 if($ClassName eq $Problem{"Type_Name"}) {
17180 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17181 }
17182 else {
17183 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17184 }
17185 }
17186 else
17187 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017188 my $TypeID = undef;
17189
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017190 if($Location=~/retval/)
17191 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017192 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017193 push(@Sentence, "Field \'".$Location."\' in return value");
17194 }
17195 else {
17196 push(@Sentence, "Return value");
17197 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017198
17199 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017200 }
17201 elsif($Location=~/this/)
17202 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017203 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017204 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17205 }
17206 else {
17207 push(@Sentence, "\'this\' pointer");
17208 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017209
17210 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017211 }
17212 else
17213 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017214
17215 my $PName = getParamName($Location);
17216 my $PPos = getParamPos($PName, $Symbol, 1);
17217
17218 if(index($Location, "->")!=-1) {
17219 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017220 }
17221 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017222 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017223 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017224 if($PName) {
17225 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017226 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017227
17228 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17229 }
17230
17231 if($Location!~/this/)
17232 {
17233 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017234 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017235 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017236 push(@Sentence, "(pointer)");
17237 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017238 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017239 push(@Sentence, "(reference)");
17240 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017241 }
17242 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017243
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017244 if($Location eq "this") {
17245 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17246 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017247 else
17248 {
17249 my $Location_T = $Location;
17250 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17251
17252 my $TypeID_Problem = $TypeID;
17253 if($Location_T) {
17254 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17255 }
17256
17257 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17258 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17259 }
17260 else {
17261 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017263 }
17264 }
17265 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017266 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017267 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 +040017268 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017269
17270 my $Sent = join(" ", @Sentence);
17271
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017272 $Sent=~s/->/./g;
17273
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017274 if($ReportFormat eq "xml")
17275 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017276 $Sent=~s/'//g;
17277 }
17278
17279 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017280}
17281
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017282sub getFieldType($$$)
17283{
17284 my ($Location, $TypeId, $LibVersion) = @_;
17285
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017286 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017287
17288 foreach my $Name (@Fields)
17289 {
17290 my %Info = get_BaseType($TypeId, $LibVersion);
17291
17292 foreach my $Pos (keys(%{$Info{"Memb"}}))
17293 {
17294 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17295 {
17296 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17297 last;
17298 }
17299 }
17300 }
17301
17302 return $TypeId;
17303}
17304
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017305sub get_XmlSign($$)
17306{
17307 my ($Symbol, $LibVersion) = @_;
17308 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17309 my $Report = "";
17310 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17311 {
17312 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017313 my $Type = $Info->{"Param"}{$Pos}{"type"};
17314 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017315 foreach my $Typedef (keys(%ChangedTypedef))
17316 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017317 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17318 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17319 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017320 }
17321 $Report .= " <param pos=\"$Pos\">\n";
17322 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017323 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017324 $Report .= " </param>\n";
17325 }
17326 if(my $Return = $Info->{"Return"})
17327 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017328 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017329 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017330 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017331 $Report .= " </retval>\n";
17332 }
17333 return $Report;
17334}
17335
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017336sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017337{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017338 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017339 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017340 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017341 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017342 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17343 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017344 next;
17345 }
17346 $Report .= " <symbol name=\"$Symbol\">\n";
17347 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017348 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017349 {
17350 if(defined $CompleteSignature{1}{$Symbol}
17351 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17352 {
17353 $P1 = get_XmlSign($Symbol, 1);
17354 $S1 = get_Signature($Symbol, 1);
17355 }
17356 elsif($Symbol=~/\A(_Z|\?)/) {
17357 $S1 = $tr_name{$Symbol};
17358 }
17359 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017360 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017361 {
17362 if(defined $CompleteSignature{2}{$Symbol}
17363 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17364 {
17365 $P2 = get_XmlSign($Symbol, 2);
17366 $S2 = get_Signature($Symbol, 2);
17367 }
17368 elsif($Symbol=~/\A(_Z|\?)/) {
17369 $S2 = $tr_name{$Symbol};
17370 }
17371 }
17372 if($S1)
17373 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017374 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017375 $Report .= $P1;
17376 $Report .= " </old>\n";
17377 }
17378 if($S2 and $S2 ne $S1)
17379 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017380 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017381 $Report .= $P2;
17382 $Report .= " </new>\n";
17383 }
17384 $Report .= " </symbol>\n";
17385 }
17386 $Report .= "</symbols_info>\n";
17387 return $Report;
17388}
17389
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017390sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017391{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017392 my ($Level, $Report) = @_;
17393 if($ReportFormat eq "xml") {
17394 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017395 }
17396 if($StdOut)
17397 { # --stdout option
17398 print STDOUT $Report;
17399 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017400 else
17401 {
17402 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017403 mkpath(get_dirname($RPath));
17404
17405 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17406 print REPORT $Report;
17407 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017408 }
17409}
17410
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017411sub getReport($)
17412{
17413 my $Level = $_[0];
17414 if($ReportFormat eq "xml")
17415 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017416 if($Level eq "Join")
17417 {
17418 my $Report = "<reports>\n";
17419 $Report .= getReport("Binary");
17420 $Report .= getReport("Source");
17421 $Report .= "</reports>\n";
17422 return $Report;
17423 }
17424 else
17425 {
17426 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17427 my ($Summary, $MetaData) = get_Summary($Level);
17428 $Report .= $Summary."\n";
17429 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17430 $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 +040017431
17432 # additional symbols info (if needed)
17433 # $Report .= get_Report_SymbolsInfo($Level);
17434
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017435 $Report .= "</report>\n";
17436 return $Report;
17437 }
17438 }
17439 else
17440 { # HTML
17441 my $CssStyles = readModule("Styles", "Report.css");
17442 my $JScripts = readModule("Scripts", "Sections.js");
17443 if($Level eq "Join")
17444 {
17445 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17446 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017447 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017448 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17449 my $Description = "API/ABI compatibility report for the $TargetTitle $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017450 my ($BSummary, $BMetaData) = get_Summary("Binary");
17451 my ($SSummary, $SMetaData) = get_Summary("Source");
17452 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 +030017453 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017454 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017455 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17456 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017457 </div>";
17458 $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>";
17459 $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 Ponomarenko41834e32015-09-04 12:30:41 +030017460 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017461 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017462 return $Report;
17463 }
17464 else
17465 {
17466 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017467 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17468 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17469 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 +040017470 if($Level eq "Binary")
17471 {
17472 if(getArch(1) eq getArch(2)
17473 and getArch(1) ne "unknown") {
17474 $Description .= " on ".showArch(getArch(1));
17475 }
17476 }
17477 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 +030017478 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017479 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17480 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17481 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017482 $Report .= "</div>\n<br/><br/><br/>\n";
17483 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017484 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017485 return $Report;
17486 }
17487 }
17488}
17489
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017490sub getLegend()
17491{
17492 return "<br/>
17493<table class='summary'>
17494<tr>
17495 <td class='new'>added</td>
17496 <td class='passed'>compatible</td>
17497</tr>
17498<tr>
17499 <td class='warning'>warning</td>
17500 <td class='failed'>incompatible</td>
17501</tr></table>\n";
17502}
17503
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017504sub createReport()
17505{
17506 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017507 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017508 writeReport("Join", getReport("Join"));
17509 }
17510 elsif($DoubleReport)
17511 { # default
17512 writeReport("Binary", getReport("Binary"));
17513 writeReport("Source", getReport("Source"));
17514 }
17515 elsif($BinaryOnly)
17516 { # --binary
17517 writeReport("Binary", getReport("Binary"));
17518 }
17519 elsif($SourceOnly)
17520 { # --source
17521 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017522 }
17523}
17524
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017525sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017526{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017527 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017528
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017529 $Footer .= "<hr/>";
17530 $Footer .= "<div class='footer' align='right'><i>Generated on ".localtime(time);
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017531 $Footer .= " by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017532 $Footer .= "</i></div>";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017533 $Footer .= "<br/>\n";
17534
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 Ponomarenko41834e32015-09-04 12:30:41 +030021122 <br/><br/>\n".getReportFooter()."
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
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022282 if(not $CmpSystems)
22283 {
22284 $BinaryOnly = 0;
22285 $SourceOnly = 0;
22286 }
22287
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022288 $DoubleReport = 1;
22289 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022290
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022291 if($OutputReportPath)
22292 { # --report-path
22293 $DoubleReport = 0;
22294 $JoinReport = 1;
22295 }
22296 }
22297 elsif($BinaryOnly or $SourceOnly)
22298 { # --binary or --source
22299 $DoubleReport = 0;
22300 $JoinReport = 0;
22301 }
22302 if($UseXML)
22303 { # --xml option
22304 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022305 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022306 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022307 if($ReportFormat)
22308 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022309 $ReportFormat = lc($ReportFormat);
22310 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022311 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022312 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022313 if($ReportFormat eq "htm")
22314 { # HTM == HTML
22315 $ReportFormat = "html";
22316 }
22317 elsif($ReportFormat eq "xml")
22318 { # --report-format=XML equal to --xml
22319 $UseXML = 1;
22320 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022321 }
22322 else
22323 { # default: HTML
22324 $ReportFormat = "html";
22325 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022326 if($DumpFormat)
22327 { # validate
22328 $DumpFormat = lc($DumpFormat);
22329 if($DumpFormat!~/\A(xml|perl)\Z/) {
22330 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22331 }
22332 if($DumpFormat eq "xml")
22333 { # --dump-format=XML equal to --xml
22334 $UseXML = 1;
22335 }
22336 }
22337 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022338 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022339 $DumpFormat = "perl";
22340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022341 if($Quiet and $LogMode!~/a|n/)
22342 { # --quiet log
22343 if(-f $COMMON_LOG_PATH) {
22344 unlink($COMMON_LOG_PATH);
22345 }
22346 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022347 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022348 $CheckUndefined = 1;
22349 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022350 if($TestTool and $UseDumps)
22351 { # --test && --use-dumps == --test-dump
22352 $TestDump = 1;
22353 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022354 if($Tolerant)
22355 { # enable all
22356 $Tolerance = 1234;
22357 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022358 if($Help)
22359 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022360 HELP_MESSAGE();
22361 exit(0);
22362 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022363 if($InfoMsg)
22364 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022365 INFO_MESSAGE();
22366 exit(0);
22367 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022368 if($ShowVersion)
22369 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022370 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 +040022371 exit(0);
22372 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022373 if($DumpVersion)
22374 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022375 printMsg("INFO", $TOOL_VERSION);
22376 exit(0);
22377 }
22378 if($ExtendedCheck) {
22379 $CheckHeadersOnly = 1;
22380 }
22381 if($SystemRoot_Opt)
22382 { # user defined root
22383 if(not -e $SystemRoot_Opt) {
22384 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22385 }
22386 $SystemRoot = $SystemRoot_Opt;
22387 $SystemRoot=~s/[\/]+\Z//g;
22388 if($SystemRoot) {
22389 $SystemRoot = get_abs_path($SystemRoot);
22390 }
22391 }
22392 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022393
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022394 if($SortDump)
22395 {
22396 $Data::Dumper::Useperl = 1;
22397 $Data::Dumper::Sortkeys = \&dump_sorting;
22398 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022399
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022400 if($TargetLibsPath)
22401 {
22402 if(not -f $TargetLibsPath) {
22403 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22404 }
22405 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22406 $TargetLibs{$Lib} = 1;
22407 }
22408 }
22409 if($TargetHeadersPath)
22410 { # --headers-list
22411 if(not -f $TargetHeadersPath) {
22412 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22413 }
22414 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22415 {
22416 $TargetHeaders{1}{$Header} = 1;
22417 $TargetHeaders{2}{$Header} = 1;
22418 }
22419 }
22420 if($TargetHeader)
22421 { # --header
22422 $TargetHeaders{1}{$TargetHeader} = 1;
22423 $TargetHeaders{2}{$TargetHeader} = 1;
22424 }
22425 if($TestTool
22426 or $TestDump)
22427 { # --test, --test-dump
22428 detect_default_paths("bin|gcc"); # to compile libs
22429 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022430 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022431 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022432 exit(0);
22433 }
22434 if($DumpSystem)
22435 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022436
22437 if(not $TargetSysInfo) {
22438 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22439 }
22440
22441 if(not -d $TargetSysInfo) {
22442 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22443 }
22444
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022445 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022446 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022447 { # system XML descriptor
22448 if(not -f $DumpSystem) {
22449 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22450 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022451
22452 my $SDesc = readFile($DumpSystem);
22453 if(my $RelDir = $RelativeDirectory{1}) {
22454 $SDesc =~ s/{RELPATH}/$RelDir/g;
22455 }
22456
22457 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022458 foreach (@{$Ret->{"Tools"}})
22459 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022460 push_U($SystemPaths{"bin"}, $_);
22461 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022462 }
22463 if($Ret->{"CrossPrefix"}) {
22464 $CrossPrefix = $Ret->{"CrossPrefix"};
22465 }
22466 }
22467 elsif($SystemRoot_Opt)
22468 { # -sysroot "/" option
22469 # default target: /usr/lib, /usr/include
22470 # search libs: /usr/lib and /lib
22471 if(not -e $SystemRoot."/usr/lib") {
22472 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22473 }
22474 if(not -e $SystemRoot."/lib") {
22475 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22476 }
22477 if(not -e $SystemRoot."/usr/include") {
22478 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22479 }
22480 readSystemDescriptor("
22481 <name>
22482 $DumpSystem
22483 </name>
22484 <headers>
22485 $SystemRoot/usr/include
22486 </headers>
22487 <libs>
22488 $SystemRoot/usr/lib
22489 </libs>
22490 <search_libs>
22491 $SystemRoot/lib
22492 </search_libs>");
22493 }
22494 else {
22495 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22496 }
22497 detect_default_paths("bin|gcc"); # to check symbols
22498 if($OStarget eq "windows")
22499 { # to run dumpbin.exe
22500 # and undname.exe
22501 check_win32_env();
22502 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022503 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022504 exit(0);
22505 }
22506 if($CmpSystems)
22507 { # --cmp-systems
22508 detect_default_paths("bin"); # to extract dumps
22509 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022510 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022511 exit(0);
22512 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022513 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022514 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022515 }
22516 else
22517 { # validate library name
22518 if($TargetLibraryName=~/[\*\/\\]/) {
22519 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22520 }
22521 }
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022522 if(not $TargetTitle) {
22523 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022524 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022525
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022526 if($SymbolsListPath)
22527 {
22528 if(not -f $SymbolsListPath) {
22529 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22530 }
22531 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22532 $SymbolsList{$Interface} = 1;
22533 }
22534 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022535 if($TypesListPath)
22536 {
22537 if(not -f $TypesListPath) {
22538 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22539 }
22540 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22541 $TypesList{$Type} = 1;
22542 }
22543 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022544 if($SkipSymbolsListPath)
22545 {
22546 if(not -f $SkipSymbolsListPath) {
22547 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22548 }
22549 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022550 $SkipSymbols{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022551 }
22552 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022553 if($SkipHeadersPath)
22554 {
22555 if(not -f $SkipHeadersPath) {
22556 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22557 }
22558 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022559 { # register for both versions
22560 $SkipHeadersList{1}{$Path} = 1;
22561 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022562 my ($CPath, $Type) = classifyPath($Path);
22563 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022564 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022565 }
22566 }
22567 if($ParamNamesPath)
22568 {
22569 if(not -f $ParamNamesPath) {
22570 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22571 }
22572 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22573 {
22574 if($Line=~s/\A(\w+)\;//)
22575 {
22576 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022577 if($Line=~/;(\d+);/)
22578 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022579 while($Line=~s/(\d+);(\w+)//) {
22580 $AddIntParams{$Interface}{$1}=$2;
22581 }
22582 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022583 else
22584 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022585 my $Num = 0;
22586 foreach my $Name (split(/;/, $Line)) {
22587 $AddIntParams{$Interface}{$Num++}=$Name;
22588 }
22589 }
22590 }
22591 }
22592 }
22593 if($AppPath)
22594 {
22595 if(not -f $AppPath) {
22596 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22597 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022598
22599 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022600 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022601 $SymbolsList_App{$Interface} = 1;
22602 }
22603 }
22604 if($DumpAPI)
22605 { # --dump-abi
22606 # make an API dump
22607 create_ABI_Dump();
22608 exit($COMPILE_ERRORS);
22609 }
22610 # default: compare APIs
22611 # -d1 <path>
22612 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022613 compareInit();
22614 if($JoinReport or $DoubleReport)
22615 {
22616 compareAPIs("Binary");
22617 compareAPIs("Source");
22618 }
22619 elsif($BinaryOnly) {
22620 compareAPIs("Binary");
22621 }
22622 elsif($SourceOnly) {
22623 compareAPIs("Source");
22624 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022625 exitReport();
22626}
22627
22628scenario();